THE JAVASCRIPT SYSTEM TOTAL REBUILD
This commit is contained in:
parent
b07d60d8e5
commit
cf0e32e954
|
@ -28,7 +28,10 @@
|
||||||
"twig/extra-bundle": "^3.7",
|
"twig/extra-bundle": "^3.7",
|
||||||
"twig/intl-extra": "^3.10",
|
"twig/intl-extra": "^3.10",
|
||||||
"avadim/fast-excel-reader": "^2.19",
|
"avadim/fast-excel-reader": "^2.19",
|
||||||
"openswoole/core": "22.1.5"
|
"openswoole/core": "22.1.5",
|
||||||
|
"ttatpuot/cdek-sdk2.0": "^1.2",
|
||||||
|
"guzzlehttp/guzzle": "^7.9",
|
||||||
|
"php-http/guzzle7-adapter": "^1.0"
|
||||||
},
|
},
|
||||||
"autoload": {
|
"autoload": {
|
||||||
"psr-4": {
|
"psr-4": {
|
||||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -40,23 +40,31 @@ final class account extends core
|
||||||
public function write(array $parameters = []): void
|
public function write(array $parameters = []): void
|
||||||
{
|
{
|
||||||
if (!empty($parameters) && $this->account instanceof model) {
|
if (!empty($parameters) && $this->account instanceof model) {
|
||||||
// Found data of the program and active account
|
// Received parameters and initialized account
|
||||||
|
|
||||||
|
// Declaring the buffer of deserialized parameters
|
||||||
|
$deserialized = [];
|
||||||
|
|
||||||
foreach ($parameters as $name => $value) {
|
foreach ($parameters as $name => $value) {
|
||||||
// Iterate over parameters
|
// Iterate over parameters
|
||||||
|
|
||||||
// Validation of the parameter
|
// Validation of the parameter value
|
||||||
if (mb_strlen($value) > 4096) continue;
|
if (mb_strlen($value) > 4096) continue;
|
||||||
|
|
||||||
// Convert name to multidimensional array
|
// Declaring the buffer of deserialized parameter
|
||||||
foreach (array_reverse(explode('_', $name)) as $key) $parameter = [$key => $parameter ?? json_validate($value) ? json_decode($value, true, 10) : $value];
|
$parameter = null;
|
||||||
|
|
||||||
// Write data of to the buffer parameter in the implement object of account document from ArangoDB
|
// Deserializing name to multidimensional array
|
||||||
$this->account->buffer = $parameter + $this->account->buffer ?? [];
|
foreach (array_reverse(explode('_', $name)) as $key)
|
||||||
|
$parameter = [$key => $parameter ?? (json_validate($value) ? json_decode($value, true, 10) : $value)];
|
||||||
|
|
||||||
|
// Writing into the buffer of deserialized parameters
|
||||||
|
$deserialized = array_merge_recursive($parameter, $deserialized);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Write from implement object to account document from ArangoDB
|
|
||||||
document::update($this->account->__document(), $this->errors['account']);
|
// Write to the account document from ArangoDB
|
||||||
|
if (!empty($deserialized)) $this->account->write($deserialized, $this->errors['account']);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -24,6 +24,11 @@ use mirzaev\arangodb\document;
|
||||||
*/
|
*/
|
||||||
final class cart extends core
|
final class cart extends core
|
||||||
{
|
{
|
||||||
|
/**
|
||||||
|
* Instance of the cart
|
||||||
|
*/
|
||||||
|
protected readonly ?model $cart;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Registry of errors
|
* Registry of errors
|
||||||
*/
|
*/
|
||||||
|
@ -57,6 +62,22 @@ final class cart extends core
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Initializing the cart
|
||||||
|
$this->cart = $this->account?->cart() ?? $this->session?->cart();
|
||||||
|
|
||||||
|
// Initializing the cart data
|
||||||
|
$this->view->cart = [
|
||||||
|
'summary' => $this->cart?->summary(currency: $this->currency),
|
||||||
|
'products' => $this->cart?->products(language: $this->language, currency: $this->currency)
|
||||||
|
];
|
||||||
|
|
||||||
|
// Initializing types of avaiabld deliveries
|
||||||
|
$this->view->deliveries = [
|
||||||
|
'cdek' => [
|
||||||
|
'label' => 'CDEK'
|
||||||
|
]
|
||||||
|
];
|
||||||
|
|
||||||
if ($_SERVER['REQUEST_METHOD'] === 'GET') {
|
if ($_SERVER['REQUEST_METHOD'] === 'GET') {
|
||||||
// GET request
|
// GET request
|
||||||
|
|
||||||
|
@ -135,6 +156,12 @@ final class cart extends core
|
||||||
if ($product instanceof product) {
|
if ($product instanceof product) {
|
||||||
// Initialized the product
|
// Initialized the product
|
||||||
|
|
||||||
|
// Initializing the cart
|
||||||
|
$this->cart = $this->account?->cart() ?? $this->session?->cart();
|
||||||
|
|
||||||
|
if ($this->cart instanceof model) {
|
||||||
|
// Initialized the cart
|
||||||
|
|
||||||
// Initializing the buffer with amount of the product in the cart
|
// Initializing the buffer with amount of the product in the cart
|
||||||
$amount = $this->cart->count(product: $product, limit: 100, errors: $this->errors['cart']) ?? 0;
|
$amount = $this->cart->count(product: $product, limit: 100, errors: $this->errors['cart']) ?? 0;
|
||||||
|
|
||||||
|
@ -230,6 +257,7 @@ final class cart extends core
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Initializing a response headers
|
// Initializing a response headers
|
||||||
header('Content-Type: application/json');
|
header('Content-Type: application/json');
|
||||||
|
@ -272,6 +300,12 @@ final class cart extends core
|
||||||
if ($_SERVER['REQUEST_METHOD'] === 'POST') {
|
if ($_SERVER['REQUEST_METHOD'] === 'POST') {
|
||||||
// POST request
|
// POST request
|
||||||
|
|
||||||
|
// Initializing the cart
|
||||||
|
$this->cart = $this->account?->cart() ?? $this->session?->cart();
|
||||||
|
|
||||||
|
if ($this->cart instanceof model) {
|
||||||
|
// Initialized the cart
|
||||||
|
|
||||||
// Initializing summary data of the cart
|
// Initializing summary data of the cart
|
||||||
$summary = $this->cart?->summary(currency: $this->currency, errors: $this->errors['cart']);
|
$summary = $this->cart?->summary(currency: $this->currency, errors: $this->errors['cart']);
|
||||||
|
|
||||||
|
@ -302,6 +336,7 @@ final class cart extends core
|
||||||
// Exit (success)
|
// Exit (success)
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Exit (fail)
|
// Exit (fail)
|
||||||
return null;
|
return null;
|
||||||
|
|
|
@ -53,7 +53,7 @@ final class catalog extends core
|
||||||
filter: "d.identifier == @identifier && d.deleted != true && d.hidden != true",
|
filter: "d.identifier == @identifier && d.deleted != true && d.hidden != true",
|
||||||
sort: 'd.created DESC',
|
sort: 'd.created DESC',
|
||||||
amount: 1,
|
amount: 1,
|
||||||
return: '{identifier: d.identifier, name: d.name.@language, description: d.description.@language, cost: d.cost, weight: d.weight, dimensions: d.dimensions, brand: d.brand.@language, compatibility: d.compatibility.@language, cost: d.cost.@currency, images: d.images[*].storage}',
|
return: '{identifier: d.identifier, name: d.name.@language, description: d.description.@language, cost: d.cost.@currency, weight: d.weight, dimensions: d.dimensions, brand: d.brand.@language, compatibility: d.compatibility.@language, cost: d.cost.@currency, images: d.images[*].storage}',
|
||||||
language: $this->language,
|
language: $this->language,
|
||||||
currency: $this->currency,
|
currency: $this->currency,
|
||||||
parameters: ['identifier' => $product],
|
parameters: ['identifier' => $product],
|
||||||
|
@ -186,7 +186,7 @@ final class catalog extends core
|
||||||
if (isset($text)) {
|
if (isset($text)) {
|
||||||
// Received and validated text
|
// Received and validated text
|
||||||
|
|
||||||
// Writing to the account buffer
|
// Writing to the account buffer (useless becouse rewrite itself to null with every request)
|
||||||
$this->account?->write(
|
$this->account?->write(
|
||||||
[
|
[
|
||||||
'catalog' => [
|
'catalog' => [
|
||||||
|
@ -197,7 +197,7 @@ final class catalog extends core
|
||||||
]
|
]
|
||||||
);
|
);
|
||||||
|
|
||||||
// Writing to the session buffer
|
// Writing to the session buffer (useless becouse rewrite itself to null with every request)
|
||||||
$this->session?->write(
|
$this->session?->write(
|
||||||
[
|
[
|
||||||
'catalog' => [
|
'catalog' => [
|
||||||
|
@ -296,7 +296,7 @@ final class catalog extends core
|
||||||
) ?? null;
|
) ?? null;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (isset($brand) || (isset($this->view->products) && count($this->view->products) > 0)) {
|
if (isset($brand) || isset($text) || (isset($this->view->products) && count($this->view->products) > 0)) {
|
||||||
// Received and validated at least one of filters or amount of rendered products is more than 0
|
// Received and validated at least one of filters or amount of rendered products is more than 0
|
||||||
|
|
||||||
// Search for filters and write to the buffer of global variables of view templater
|
// Search for filters and write to the buffer of global variables of view templater
|
||||||
|
@ -355,7 +355,7 @@ final class catalog extends core
|
||||||
sprintf(
|
sprintf(
|
||||||
<<<javascript
|
<<<javascript
|
||||||
if (typeof _window === 'undefined') {
|
if (typeof _window === 'undefined') {
|
||||||
_window = setTimeout(() => core.catalog.product_system('%s'), 500);
|
_window = setTimeout(() => core.catalog.product.system('%s'), 500);
|
||||||
}
|
}
|
||||||
javascript,
|
javascript,
|
||||||
$this->view->product['identifier']
|
$this->view->product['identifier']
|
||||||
|
|
|
@ -138,15 +138,11 @@ class core extends controller
|
||||||
// Initializing of the currency
|
// Initializing of the currency
|
||||||
$this->currency = $this->account?->currency ?? $this->session?->buffer['currency'] ?? $this->settings?->currency ?? currency::usd;
|
$this->currency = $this->account?->currency ?? $this->session?->buffer['currency'] ?? $this->settings?->currency ?? currency::usd;
|
||||||
|
|
||||||
// Initializing of the cart
|
|
||||||
$this->cart = $this->account?->cart() ?? $this->session?->cart();
|
|
||||||
|
|
||||||
// Initializing of preprocessor of views
|
// Initializing of preprocessor of views
|
||||||
$this->view = new templater(
|
$this->view = new templater(
|
||||||
session: $this->session,
|
session: $this->session,
|
||||||
account: $this->account,
|
account: $this->account,
|
||||||
settings: $this->settings,
|
settings: $this->settings
|
||||||
cart: $this->cart
|
|
||||||
);
|
);
|
||||||
|
|
||||||
// @todo перенести в middleware
|
// @todo перенести в middleware
|
||||||
|
|
|
@ -0,0 +1,78 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
declare(strict_types=1);
|
||||||
|
|
||||||
|
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\cart,
|
||||||
|
mirzaev\arming_bot\models\product,
|
||||||
|
mirzaev\arming_bot\models\menu;
|
||||||
|
|
||||||
|
// Framework for ArangoDB
|
||||||
|
use mirzaev\arangodb\document;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Controller of cdek
|
||||||
|
*
|
||||||
|
* @package mirzaev\arming_bot\controllers
|
||||||
|
*
|
||||||
|
* @license http://www.wtfpl.net/ Do What The Fuck You Want To Public License
|
||||||
|
* @author Arsen Mirzaev Tatyano-Muradovich <arsen@mirzaev.sexy>
|
||||||
|
*/
|
||||||
|
final class cdek extends core
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* Registry of errors
|
||||||
|
*/
|
||||||
|
protected array $errors = [
|
||||||
|
'delivery' => []
|
||||||
|
];
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Calculate
|
||||||
|
*
|
||||||
|
* @param array $parameters Parameters of the request (POST + GET)
|
||||||
|
*/
|
||||||
|
public function calculate(array $parameters = []): ?string
|
||||||
|
{
|
||||||
|
if ($_SERVER['REQUEST_METHOD'] === 'POST') {
|
||||||
|
// POST request
|
||||||
|
|
||||||
|
$this->model::calculate();
|
||||||
|
|
||||||
|
die;
|
||||||
|
|
||||||
|
// Initializing a response headers
|
||||||
|
header('Content-Type: application/json');
|
||||||
|
header('Content-Encoding: none');
|
||||||
|
header('X-Accel-Buffering: no');
|
||||||
|
|
||||||
|
// Initializing of the output buffer
|
||||||
|
ob_start();
|
||||||
|
|
||||||
|
// Generating the reponse
|
||||||
|
echo json_encode(
|
||||||
|
[
|
||||||
|
'main' => '',
|
||||||
|
'errors' => $this->errors
|
||||||
|
]
|
||||||
|
);
|
||||||
|
|
||||||
|
// Initializing a response headers
|
||||||
|
header('Content-Length: ' . ob_get_length());
|
||||||
|
|
||||||
|
// Sending and deinitializing of the output buffer
|
||||||
|
ob_end_flush();
|
||||||
|
flush();
|
||||||
|
|
||||||
|
// Exit (success)
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Exit (fail)
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
|
@ -167,23 +167,30 @@ final class session extends core
|
||||||
public function write(array $parameters = []): void
|
public function write(array $parameters = []): void
|
||||||
{
|
{
|
||||||
if (!empty($parameters) && $this->session instanceof model) {
|
if (!empty($parameters) && $this->session instanceof model) {
|
||||||
// Found data of the program and active session
|
// Received parameters and initialized session
|
||||||
|
|
||||||
|
// Declaring the buffer of deserialized parameters
|
||||||
|
$deserialized = [];
|
||||||
|
|
||||||
foreach ($parameters as $name => $value) {
|
foreach ($parameters as $name => $value) {
|
||||||
// Iterate over parameters
|
// Iterate over parameters
|
||||||
|
|
||||||
// Validation of the parameter
|
// Validation of the parameter value
|
||||||
if (mb_strlen($value) > 4096) continue;
|
if (mb_strlen($value) > 4096) continue;
|
||||||
|
|
||||||
// Convert name to multidimensional array
|
// Declaring the buffer of deserialized parameter
|
||||||
foreach (array_reverse(explode('_', $name)) as $key) $parameter = [$key => $parameter ?? json_validate($value) ? json_decode($value, true, 10) : $value];
|
$parameter = null;
|
||||||
|
|
||||||
// Write data of to the buffer parameter in the implement object of session document from ArangoDB
|
// Deserializing name to multidimensional array
|
||||||
$this->session->buffer = $parameter + ($this->session->buffer ?? []);
|
foreach (array_reverse(explode('_', $name)) as $key)
|
||||||
|
$parameter = [$key => $parameter ?? (json_validate($value) ? json_decode($value, true, 10) : $value)];
|
||||||
|
|
||||||
|
// Writing into the buffer of deserialized parameters
|
||||||
|
$deserialized = array_merge_recursive($parameter, $deserialized);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Write from implement object to session document from ArangoDB
|
// Write to the session document from ArangoDB
|
||||||
document::update($this->session->__document(), $this->errors['session']);
|
if (!empty($deserialized)) $this->session->write($deserialized, $this->errors['session']);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -106,7 +106,7 @@ final class cart extends core implements document_interface, collection_interfac
|
||||||
}
|
}
|
||||||
|
|
||||||
// Exit (success)
|
// Exit (success)
|
||||||
return $products;
|
return isset($products['amount']) ? [$products['document']['_id'] => $products] : $products;
|
||||||
} else throw new exception('Failed to initialize ' . product::TYPE . ' collection: ' . product::COLLECTION);
|
} else throw new exception('Failed to initialize ' . product::TYPE . ' collection: ' . product::COLLECTION);
|
||||||
} else throw new exception('Failed to initialize ' . reservation::TYPE . ' collection: ' . reservation::COLLECTION);
|
} else throw new exception('Failed to initialize ' . reservation::TYPE . ' collection: ' . reservation::COLLECTION);
|
||||||
} else throw new exception('Failed to initialize ' . static::TYPE . ' collection: ' . static::COLLECTION);
|
} else throw new exception('Failed to initialize ' . static::TYPE . ' collection: ' . static::COLLECTION);
|
||||||
|
|
|
@ -0,0 +1,84 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
declare(strict_types=1);
|
||||||
|
|
||||||
|
namespace mirzaev\arming_bot\models\deliveries;
|
||||||
|
|
||||||
|
// Files of the project
|
||||||
|
use mirzaev\arming_bot\models\core,
|
||||||
|
mirzaev\arming_bot\models\traits\document as document_trait,
|
||||||
|
mirzaev\arming_bot\models\interfaces\document as document_interface,
|
||||||
|
mirzaev\arming_bot\models\interfaces\collection as collection_interface;
|
||||||
|
|
||||||
|
// The HTTP PSR-18 adapter for Guzzle HTTP client
|
||||||
|
use Http\Adapter\Guzzle7\Client as guzzle;
|
||||||
|
|
||||||
|
// Framework for CDEK
|
||||||
|
use CdekSDK2\Client as client,
|
||||||
|
CdekSDK2\Dto\CityList as cities;
|
||||||
|
|
||||||
|
// Built-in libraries
|
||||||
|
use exception;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Model of CDEK
|
||||||
|
*
|
||||||
|
* @package mirzaev\arming_bot\models\deliveries
|
||||||
|
*
|
||||||
|
* @license http://www.wtfpl.net/ Do What The Fuck You Want To Public License
|
||||||
|
* @author Arsen Mirzaev Tatyano-Muradovich <arsen@mirzaev.sexy>
|
||||||
|
*/
|
||||||
|
final class cdek extends core implements document_interface, collection_interface
|
||||||
|
{
|
||||||
|
use document_trait;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Name of the collection in ArangoDB
|
||||||
|
*/
|
||||||
|
final public const string COLLECTION = 'delivery';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Calculate
|
||||||
|
*
|
||||||
|
* Calculate delivery by CDEK
|
||||||
|
*
|
||||||
|
* @param array &$errors Registry of errors
|
||||||
|
*
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
public static function calculate(array &$errors = []): static|null
|
||||||
|
{
|
||||||
|
try {
|
||||||
|
//
|
||||||
|
/* $client = new client(new guzzle, 'account', 'secure'); */
|
||||||
|
$client = new client(new guzzle);
|
||||||
|
$client->setTest(true);
|
||||||
|
|
||||||
|
$result = $client->cities()->getFiltered(['country_codes' => 'RU', 'city' => 'зеленогорск']);
|
||||||
|
|
||||||
|
if ($result->isOk()) {
|
||||||
|
//
|
||||||
|
|
||||||
|
//Запрос успешно выполнился
|
||||||
|
$cities = $client->formatResponseList($result, cities::class);
|
||||||
|
|
||||||
|
foreach ($cities->items as $city) {
|
||||||
|
var_dump($city);
|
||||||
|
}
|
||||||
|
|
||||||
|
die;
|
||||||
|
}
|
||||||
|
} 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 null;
|
||||||
|
}
|
||||||
|
}
|
|
@ -5,7 +5,9 @@ declare(strict_types=1);
|
||||||
namespace mirzaev\arming_bot\models\traits;
|
namespace mirzaev\arming_bot\models\traits;
|
||||||
|
|
||||||
// Files of the project
|
// Files of the project
|
||||||
use mirzaev\arming_bot\models\interfaces\collection as collection_interface;
|
use mirzaev\arming_bot\models\interfaces\collection as collection_interface,
|
||||||
|
mirzaev\arming_bot\models\enumerations\language,
|
||||||
|
mirzaev\arming_bot\models\enumerations\currency;
|
||||||
|
|
||||||
// Library for ArangoDB
|
// Library for ArangoDB
|
||||||
use ArangoDBClient\Document as _document;
|
use ArangoDBClient\Document as _document;
|
||||||
|
@ -47,12 +49,19 @@ trait buffer
|
||||||
if (collection::initialize(static::COLLECTION, static::TYPE, errors: $errors)) {
|
if (collection::initialize(static::COLLECTION, static::TYPE, errors: $errors)) {
|
||||||
// Initialized the collection
|
// Initialized the collection
|
||||||
|
|
||||||
// The instance of the document from ArangoDB is initialized?
|
// Is the instance of the document from ArangoDB are initialized?
|
||||||
isset($this->document) || throw new exception('The instance of the sessoin document from ArangoDB is not initialized');
|
if (!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 document from ArangoDB
|
// Writing data into buffer of the instance of the document from ArangoDB
|
||||||
$this->document->buffer = array_replace_recursive($this->document->buffer ?? [], $data);
|
$this->document->buffer = array_replace_recursive($this->document->buffer ?? [], $data);
|
||||||
|
|
||||||
|
// Is the buffer of the instance of the document from ArangoDB exceed 10 megabytes?
|
||||||
|
if (mb_strlen(json_encode($this->document->buffer)) > 10485760) throw new exception('The buffer size exceeds 10 megabytes');
|
||||||
|
|
||||||
|
// Serializing parameters
|
||||||
|
if ($this->document->language instanceof language) $this->document->language = $this->document->language->name;
|
||||||
|
if ($this->document->currency instanceof currency) $this->document->currency = $this->document->currency->name;
|
||||||
|
|
||||||
// Writing to ArangoDB and exit (success)
|
// Writing to ArangoDB and exit (success)
|
||||||
return document::update($this->document, errors: $errors);
|
return document::update($this->document, errors: $errors);
|
||||||
} else throw new exception('Failed to initialize ' . static::TYPE . ' collection: ' . static::COLLECTION);
|
} else throw new exception('Failed to initialize ' . static::TYPE . ' collection: ' . static::COLLECTION);
|
||||||
|
|
|
@ -47,6 +47,7 @@ $router
|
||||||
->write('/account/write', 'account', 'write', 'POST')
|
->write('/account/write', 'account', 'write', 'POST')
|
||||||
->write('/session/write', 'session', 'write', 'POST')
|
->write('/session/write', 'session', 'write', 'POST')
|
||||||
->write('/session/connect/telegram', 'session', 'telegram', 'POST')
|
->write('/session/connect/telegram', 'session', 'telegram', 'POST')
|
||||||
|
->write('/cdek/calculate', 'deliveries\\cdek', 'calculate', 'POST')
|
||||||
/* ->write('/category/$identifier', 'catalog', 'index', 'POST') */
|
/* ->write('/category/$identifier', 'catalog', 'index', 'POST') */
|
||||||
/* ->write('/category', 'catalog', 'index', 'POST') */
|
/* ->write('/category', 'catalog', 'index', 'POST') */
|
||||||
/* ->write('/product/$identifier', 'catalog', 'product', 'POST') */
|
/* ->write('/product/$identifier', 'catalog', 'product', 'POST') */
|
||||||
|
|
|
@ -1,156 +0,0 @@
|
||||||
"use strict";
|
|
||||||
|
|
||||||
// Import dependencies
|
|
||||||
import("/js/core.js").then(() =>
|
|
||||||
import("/js/damper.js").then(() =>
|
|
||||||
import("/js/telegram.js").then(() => {
|
|
||||||
const dependencies = setInterval(() => {
|
|
||||||
if (
|
|
||||||
typeof core === "function" &&
|
|
||||||
typeof core.damper === "function" &&
|
|
||||||
typeof core.telegram === "function"
|
|
||||||
) {
|
|
||||||
clearInterval(dependencies);
|
|
||||||
clearTimeout(timeout);
|
|
||||||
initialization();
|
|
||||||
}
|
|
||||||
}, 10);
|
|
||||||
const timeout = setTimeout(() => {
|
|
||||||
clearInterval(dependencies);
|
|
||||||
initialization();
|
|
||||||
}, 5000);
|
|
||||||
|
|
||||||
function initialization() {
|
|
||||||
if (typeof core.account === "undefined") {
|
|
||||||
// Not initialized
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @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 <arsen@mirzaev.sexy>
|
|
||||||
*/
|
|
||||||
core.account = class account {
|
|
||||||
// Wrap of indicator of the account
|
|
||||||
static wrap = document.getElementById("account");
|
|
||||||
|
|
||||||
// Indicator of the account
|
|
||||||
static indicator = this.wrap.getElementsByTagName("i")[0];
|
|
||||||
|
|
||||||
// Description of the account
|
|
||||||
static description = this.wrap.getElementsByTagName("small")[0];
|
|
||||||
|
|
||||||
// Statuc of the account
|
|
||||||
static connected = false;
|
|
||||||
|
|
||||||
// Duration of the disconnected status
|
|
||||||
static timeout = 0;
|
|
||||||
|
|
||||||
// Instance of the time counter in disconnected status
|
|
||||||
static counter;
|
|
||||||
|
|
||||||
// Socket address (xn--e1ajlli это сокет)
|
|
||||||
static socket = "wss://arming.dev.mirzaev.sexy:9502";
|
|
||||||
|
|
||||||
// Instance of account to the socket
|
|
||||||
static session;
|
|
||||||
|
|
||||||
// Iterval for reconnect
|
|
||||||
static interval;
|
|
||||||
|
|
||||||
// Attempts to connect (when core.account.readyState === 0)
|
|
||||||
static attempts = 0;
|
|
||||||
|
|
||||||
// Interval for block
|
|
||||||
static block;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Authentication
|
|
||||||
*
|
|
||||||
* @return {void}
|
|
||||||
*/
|
|
||||||
static authentication() {
|
|
||||||
core.status_loading.removeAttribute("disabled");
|
|
||||||
|
|
||||||
const timer_for_response = setTimeout(() => {
|
|
||||||
core.status_loading.setAttribute("disabled", true);
|
|
||||||
}, 3000);
|
|
||||||
|
|
||||||
if (core.telegram.api.initData.length > 0) {
|
|
||||||
core
|
|
||||||
.request(
|
|
||||||
"/session/connect/telegram",
|
|
||||||
core.telegram.api.initData,
|
|
||||||
)
|
|
||||||
.then((json) => {
|
|
||||||
if (
|
|
||||||
json.errors !== null &&
|
|
||||||
typeof json.errors === "object" &&
|
|
||||||
json.errors.length > 0
|
|
||||||
) {
|
|
||||||
// Errors received
|
|
||||||
} else {
|
|
||||||
// Errors not received
|
|
||||||
|
|
||||||
if (json.connected === true) {
|
|
||||||
core.status_loading.setAttribute("disabled", true);
|
|
||||||
clearTimeout(timer_for_response);
|
|
||||||
|
|
||||||
const a =
|
|
||||||
core.status_account.getElementsByTagName("a")[0];
|
|
||||||
a.setAttribute("onclick", "core.account.profile()");
|
|
||||||
a.innerText = json.domain.length > 0
|
|
||||||
? "@" + json.domain
|
|
||||||
: "ERROR";
|
|
||||||
}
|
|
||||||
|
|
||||||
if (
|
|
||||||
json.language !== null &&
|
|
||||||
typeof json.language === "string" &&
|
|
||||||
json.langiage.length === 2
|
|
||||||
) {
|
|
||||||
core.language = json.language;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Buffer
|
|
||||||
*/
|
|
||||||
static buffer = class buffer {
|
|
||||||
/**
|
|
||||||
* Write to the account buffer
|
|
||||||
*
|
|
||||||
* @param {string} name Name of the parameter
|
|
||||||
* @param {string} value Value of the parameter (it can be JSON)
|
|
||||||
*
|
|
||||||
* @return {void}
|
|
||||||
*/
|
|
||||||
static write(name, value) {
|
|
||||||
if (typeof name === "string" && typeof value === "string") {
|
|
||||||
//
|
|
||||||
|
|
||||||
// Send request to the server
|
|
||||||
core.request(
|
|
||||||
"/account/write",
|
|
||||||
`${name}=${value}`,
|
|
||||||
"POST",
|
|
||||||
{},
|
|
||||||
null,
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
|
||||||
};
|
|
||||||
}
|
|
||||||
}
|
|
||||||
})
|
|
||||||
)
|
|
||||||
);
|
|
|
@ -1,28 +1,7 @@
|
||||||
"use strict";
|
"use strict";
|
||||||
|
|
||||||
// Import dependencies
|
core.modules.connect(["session", "account", "telegram"])
|
||||||
import("/js/core.js").then(() =>
|
.then(() => {
|
||||||
import("/js/damper.js").then(() =>
|
|
||||||
import("/js/telegram.js").then(() =>
|
|
||||||
import("/js/account.js").then(() => {
|
|
||||||
const dependencies = setInterval(() => {
|
|
||||||
if (
|
|
||||||
typeof core === "function" &&
|
|
||||||
typeof core.damper === "function" &&
|
|
||||||
typeof core.telegram === "function" &&
|
|
||||||
typeof core.account === "function"
|
|
||||||
) {
|
|
||||||
clearInterval(dependencies);
|
|
||||||
clearTimeout(timeout);
|
|
||||||
initialization();
|
|
||||||
}
|
|
||||||
}, 10);
|
|
||||||
const timeout = setTimeout(() => {
|
|
||||||
clearInterval(dependencies);
|
|
||||||
initialization();
|
|
||||||
}, 5000);
|
|
||||||
|
|
||||||
function initialization() {
|
|
||||||
//
|
//
|
||||||
const { initData, initDataUnsafe, ...data } = core.telegram.api;
|
const { initData, initDataUnsafe, ...data } = core.telegram.api;
|
||||||
|
|
||||||
|
@ -38,8 +17,4 @@ import("/js/core.js").then(() =>
|
||||||
|
|
||||||
//
|
//
|
||||||
core.telegram.api.ready();
|
core.telegram.api.ready();
|
||||||
}
|
});
|
||||||
})
|
|
||||||
)
|
|
||||||
)
|
|
||||||
);
|
|
||||||
|
|
|
@ -1,430 +0,0 @@
|
||||||
"use strict";
|
|
||||||
|
|
||||||
// Import dependencies
|
|
||||||
import("/js/core.js").then(() =>
|
|
||||||
import("/js/damper.js").then(() => {
|
|
||||||
const dependencies = setInterval(() => {
|
|
||||||
if (
|
|
||||||
typeof core === "function" &&
|
|
||||||
typeof core.damper === "function"
|
|
||||||
) {
|
|
||||||
clearInterval(dependencies);
|
|
||||||
clearTimeout(timeout);
|
|
||||||
initialization();
|
|
||||||
}
|
|
||||||
}, 10);
|
|
||||||
const timeout = setTimeout(() => {
|
|
||||||
clearInterval(dependencies);
|
|
||||||
initialization();
|
|
||||||
}, 5000);
|
|
||||||
|
|
||||||
function initialization() {
|
|
||||||
if (typeof core.cart === "undefined") {
|
|
||||||
// Not initialized
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @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 <arsen@mirzaev.sexy>
|
|
||||||
*/
|
|
||||||
core.cart = class cart {
|
|
||||||
/**
|
|
||||||
* Toggle
|
|
||||||
*
|
|
||||||
* Toggle the product in the cart (interface)
|
|
||||||
*
|
|
||||||
* @param {HTMLButtonElement|HTMLInputElement} element Handler elememnt of the product
|
|
||||||
* @param {HTMLElement} product The product
|
|
||||||
* @param {bool} remove Remove the product element if json.amount === 0?
|
|
||||||
* @param {bool} force Ignore the damper? (false)
|
|
||||||
*
|
|
||||||
* @return {bool} True if an error occurs to continue the event execution
|
|
||||||
*/
|
|
||||||
static toggle(element, product, remove = false, force = false) {
|
|
||||||
// Blocking the element
|
|
||||||
element.setAttribute("disabled", "true");
|
|
||||||
|
|
||||||
// Execute under damper
|
|
||||||
this.toggle_damper(
|
|
||||||
element,
|
|
||||||
product,
|
|
||||||
"toggle",
|
|
||||||
undefined,
|
|
||||||
remove,
|
|
||||||
force,
|
|
||||||
);
|
|
||||||
|
|
||||||
// Exit (success)
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Toggle
|
|
||||||
*
|
|
||||||
* Toggle the product in the cart (damper)
|
|
||||||
*
|
|
||||||
* @param {HTMLButtonElement|HTMLInputElement} element Handler elememnt of the product
|
|
||||||
* @param {HTMLElement} product The product
|
|
||||||
* @param {bool} remove Remove the product element if json.amount === 0?
|
|
||||||
* @param {bool} force Ignore the damper? (false)
|
|
||||||
*
|
|
||||||
* @return {Promise}
|
|
||||||
*/
|
|
||||||
static toggle_damper = core.damper(
|
|
||||||
(...variables) => this.product(...variables).then(this.summary),
|
|
||||||
300,
|
|
||||||
6,
|
|
||||||
);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Write
|
|
||||||
*
|
|
||||||
* Write the product in the cart (interface)
|
|
||||||
*
|
|
||||||
* @param {HTMLButtonElement|HTMLInputElement} element Handler elememnt of the product
|
|
||||||
* @param {HTMLElement} product The product
|
|
||||||
* @param {number} amount Amount of writings
|
|
||||||
* @param {bool} remove Remove the product element if json.amount === 0?
|
|
||||||
* @param {bool} force Ignore the damper? (false)
|
|
||||||
*
|
|
||||||
* @return {bool} True if an error occurs to continue the event execution
|
|
||||||
*/
|
|
||||||
static write(
|
|
||||||
element,
|
|
||||||
product,
|
|
||||||
amount = 1,
|
|
||||||
remove = false,
|
|
||||||
force = false,
|
|
||||||
) {
|
|
||||||
// Blocking the element
|
|
||||||
element.setAttribute("disabled", "true");
|
|
||||||
|
|
||||||
// Execute under damper
|
|
||||||
this.write_damper(element, product, "write", amount, remove, force);
|
|
||||||
|
|
||||||
// Exit (success)
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Write
|
|
||||||
*
|
|
||||||
* Write the product in the cart (damper)
|
|
||||||
*
|
|
||||||
* @param {HTMLButtonElement|HTMLInputElement} element Handler elememnt of the product
|
|
||||||
* @param {HTMLElement} product The product
|
|
||||||
* @param {number} amount Amount of writings
|
|
||||||
* @param {bool} remove Remove the product element if json.amount === 0?
|
|
||||||
* @param {bool} force Ignore the damper? (false)
|
|
||||||
*
|
|
||||||
* @return {Promise}
|
|
||||||
*/
|
|
||||||
static write_damper = core.damper(
|
|
||||||
(...variables) => this.product(...variables).then(this.summary),
|
|
||||||
300,
|
|
||||||
6,
|
|
||||||
);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Delete
|
|
||||||
*
|
|
||||||
* Delete the product from the cart (interface)
|
|
||||||
*
|
|
||||||
* @param {HTMLButtonElement|HTMLInputElement} element Handler elememnt of the product
|
|
||||||
* @param {HTMLElement} product The product
|
|
||||||
* @param {number} amount Amount of deletings
|
|
||||||
* @param {bool} remove Remove the product element if json.amount === 0?
|
|
||||||
* @param {bool} force Ignore the damper? (false)
|
|
||||||
*
|
|
||||||
* @return {bool} True if an error occurs to continue the event execution
|
|
||||||
*/
|
|
||||||
static delete(
|
|
||||||
element,
|
|
||||||
product,
|
|
||||||
amount = 1,
|
|
||||||
remove = false,
|
|
||||||
force = false,
|
|
||||||
) {
|
|
||||||
// Blocking the element
|
|
||||||
element.setAttribute("disabled", "true");
|
|
||||||
|
|
||||||
// Execute under damper
|
|
||||||
this.delete_damper(
|
|
||||||
element,
|
|
||||||
product,
|
|
||||||
"delete",
|
|
||||||
amount,
|
|
||||||
remove,
|
|
||||||
force,
|
|
||||||
);
|
|
||||||
|
|
||||||
// Exit (success)
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Delete
|
|
||||||
*
|
|
||||||
* Delete the product from the cart (damper)
|
|
||||||
*
|
|
||||||
* @param {HTMLButtonElement|HTMLInputElement} element Handler elememnt of the product
|
|
||||||
* @param {number} amount Amount of deletings
|
|
||||||
* @param {bool} remove Remove the product element if json.amount === 0?
|
|
||||||
* @param {bool} force Ignore the damper? (false)
|
|
||||||
*
|
|
||||||
* @return {Promise}
|
|
||||||
*/
|
|
||||||
static delete_damper = core.damper(
|
|
||||||
(...variables) => this.product(...variables).then(this.summary),
|
|
||||||
300,
|
|
||||||
6,
|
|
||||||
);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Set
|
|
||||||
*
|
|
||||||
* Set amount of the product in the cart (interface)
|
|
||||||
*
|
|
||||||
* @param {HTMLButtonElement|HTMLInputElement} element Handler elememnt of the product
|
|
||||||
* @param {HTMLElement} product The product
|
|
||||||
* @param {number} amount Amount of the product in the cart to be setted
|
|
||||||
* @param {bool} remove Remove the product element if json.amount === 0?
|
|
||||||
* @param {bool} force Ignore the damper? (false)
|
|
||||||
*
|
|
||||||
* @return {bool} True if an error occurs to continue the event execution
|
|
||||||
*/
|
|
||||||
static set(
|
|
||||||
element,
|
|
||||||
product,
|
|
||||||
amount = 1,
|
|
||||||
remove = false,
|
|
||||||
force = false,
|
|
||||||
) {
|
|
||||||
// Blocking the element
|
|
||||||
element.setAttribute("disabled", "true");
|
|
||||||
|
|
||||||
// Execute under damper
|
|
||||||
this.set_damper(element, product, "set", amount, remove, force);
|
|
||||||
|
|
||||||
// Exit (success)
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Set
|
|
||||||
*
|
|
||||||
* Set the product in the cart (damper)
|
|
||||||
*
|
|
||||||
* @param {HTMLButtonElement|HTMLInputElement} element Handler elememnt of the product
|
|
||||||
* @param {HTMLElement} product The product
|
|
||||||
* @param {number} amount Amount of the product in the cart to be setted
|
|
||||||
* @param {bool} remove Remove the product element if json.amount === 0?
|
|
||||||
* @param {bool} force Ignore the damper? (false)
|
|
||||||
*
|
|
||||||
* @return {Promise}
|
|
||||||
*/
|
|
||||||
static set_damper = core.damper(
|
|
||||||
(...parameters) => this.product(...parameters).then(this.summary),
|
|
||||||
300,
|
|
||||||
6,
|
|
||||||
);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* The product
|
|
||||||
*
|
|
||||||
* Handle the product in the cart (system)
|
|
||||||
*
|
|
||||||
* @param {HTMLButtonElement|HTMLInputElement} element Handler element of the product
|
|
||||||
* @param {HTMLElement} product The product element
|
|
||||||
* @param {string} type Type of action with the product
|
|
||||||
* @param {number} amount Amount of product to handle
|
|
||||||
* @param {bool} remove Remove the product element if json.amount === 0?
|
|
||||||
*
|
|
||||||
* @return {Promise|null}
|
|
||||||
*/
|
|
||||||
static async product(
|
|
||||||
element,
|
|
||||||
product,
|
|
||||||
type,
|
|
||||||
amount = null,
|
|
||||||
remove = false,
|
|
||||||
resolve = () => {},
|
|
||||||
reject = () => {},
|
|
||||||
) {
|
|
||||||
if (
|
|
||||||
(element instanceof HTMLButtonElement ||
|
|
||||||
element instanceof HTMLInputElement) &&
|
|
||||||
product instanceof HTMLElement
|
|
||||||
) {
|
|
||||||
// Validated
|
|
||||||
|
|
||||||
// Initializing the buffer of request body
|
|
||||||
let request = "";
|
|
||||||
|
|
||||||
// Initializing of identifier of the product
|
|
||||||
const identifier = +product.getAttribute(
|
|
||||||
"data-product-identifier",
|
|
||||||
);
|
|
||||||
|
|
||||||
if (typeof identifier === "number") {
|
|
||||||
// Validated identifier
|
|
||||||
|
|
||||||
// Writing to the buffer of request body
|
|
||||||
request += "&identifier=" + identifier;
|
|
||||||
|
|
||||||
if (
|
|
||||||
type === "toggle" ||
|
|
||||||
type === "write" ||
|
|
||||||
type === "delete" ||
|
|
||||||
type === "set"
|
|
||||||
) {
|
|
||||||
// Validated type
|
|
||||||
|
|
||||||
// Writing to the buffer of request body
|
|
||||||
request += "&type=" + type;
|
|
||||||
|
|
||||||
if (
|
|
||||||
(type === "toggle" &&
|
|
||||||
typeof amount === "undefined") ||
|
|
||||||
(type === "set" &&
|
|
||||||
amount === 0 ||
|
|
||||||
amount === 100) ||
|
|
||||||
typeof amount === "number" &&
|
|
||||||
amount > 0 &&
|
|
||||||
amount < 100
|
|
||||||
) {
|
|
||||||
// Validated amount
|
|
||||||
|
|
||||||
if (type !== "toggle") {
|
|
||||||
// Not a toggle request
|
|
||||||
|
|
||||||
// Writing to the buffer of request body
|
|
||||||
request += "&amount=" + amount;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Request
|
|
||||||
return await core.request(
|
|
||||||
"/cart/product",
|
|
||||||
request,
|
|
||||||
)
|
|
||||||
.then((json) => {
|
|
||||||
if (
|
|
||||||
json.errors !== null &&
|
|
||||||
typeof json.errors === "object" &&
|
|
||||||
json.errors.length > 0
|
|
||||||
) {
|
|
||||||
// Fail (received errors)
|
|
||||||
} else {
|
|
||||||
// Success (not received errors)
|
|
||||||
|
|
||||||
if (remove && json.amount === 0) {
|
|
||||||
// Requested deleting of the product element when there is no the product in the cart
|
|
||||||
|
|
||||||
// Deleting the product element
|
|
||||||
product.remove();
|
|
||||||
} else {
|
|
||||||
// Not requested deleting the product element when there is no the product in the cart
|
|
||||||
|
|
||||||
// Unblocking the element
|
|
||||||
element.removeAttribute("disabled");
|
|
||||||
|
|
||||||
// Writing offset of hue-rotate to indicate that the product is in the cart
|
|
||||||
product.style.setProperty(
|
|
||||||
"--hue-rotate-offset",
|
|
||||||
json.amount + "0deg",
|
|
||||||
);
|
|
||||||
|
|
||||||
// Writing attribute with amount of the product in the cart
|
|
||||||
product.setAttribute(
|
|
||||||
"data-product-amount",
|
|
||||||
json.amount,
|
|
||||||
);
|
|
||||||
|
|
||||||
// Initializing the amount <span> element
|
|
||||||
const amounts = product.querySelectorAll(
|
|
||||||
'[data-product-parameter="amount"]',
|
|
||||||
);
|
|
||||||
|
|
||||||
for (const amount of amounts) {
|
|
||||||
// Iterating over an amount elements
|
|
||||||
|
|
||||||
if (amount instanceof HTMLInputElement) {
|
|
||||||
// The <input> element
|
|
||||||
|
|
||||||
// Writing amount of the product in the cart
|
|
||||||
amount.value = json.amount;
|
|
||||||
} else {
|
|
||||||
// Not the <input> element
|
|
||||||
|
|
||||||
// Writing amount of the product in the cart
|
|
||||||
amount.innerText = json.amount;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Exit (success)
|
|
||||||
resolve();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Exit (fail)
|
|
||||||
reject();
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Summary
|
|
||||||
*
|
|
||||||
* Initialize summary of products the cart (system)
|
|
||||||
*
|
|
||||||
* @return {void}
|
|
||||||
*/
|
|
||||||
static async summary() {
|
|
||||||
// Request
|
|
||||||
return await core.request("/cart/summary")
|
|
||||||
.then((json) => {
|
|
||||||
if (
|
|
||||||
json.errors !== null &&
|
|
||||||
typeof json.errors === "object" &&
|
|
||||||
json.errors.length > 0
|
|
||||||
) {
|
|
||||||
// Fail (received errors)
|
|
||||||
} else {
|
|
||||||
// Success (not received errors)
|
|
||||||
|
|
||||||
// Initializing the summary amount <span> element
|
|
||||||
const amount = document.getElementById("amount");
|
|
||||||
|
|
||||||
// Initializing the summary cost <span> element
|
|
||||||
const cost = document.getElementById("cost");
|
|
||||||
|
|
||||||
if (amount instanceof HTMLElement) {
|
|
||||||
// Initialized the summary amount element
|
|
||||||
|
|
||||||
// Writing summmary amount into the summary amount element
|
|
||||||
amount.innerText = json.amount;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (cost instanceof HTMLElement) {
|
|
||||||
// Initialized the summary cost element
|
|
||||||
|
|
||||||
// Writing summmary cost into the summary cost element
|
|
||||||
cost.innerText = json.cost;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
};
|
|
||||||
}
|
|
||||||
}
|
|
||||||
})
|
|
||||||
);
|
|
File diff suppressed because it is too large
Load Diff
|
@ -1,324 +0,0 @@
|
||||||
"use strict";
|
|
||||||
|
|
||||||
// Import dependencies
|
|
||||||
import("/js/core.js").then(() =>
|
|
||||||
import("/js/damper.js").then(() => {
|
|
||||||
const dependencies = setInterval(() => {
|
|
||||||
if (
|
|
||||||
typeof core === "function" &&
|
|
||||||
typeof core.damper === "function"
|
|
||||||
) {
|
|
||||||
clearInterval(dependencies);
|
|
||||||
clearTimeout(timeout);
|
|
||||||
initialization();
|
|
||||||
}
|
|
||||||
}, 10);
|
|
||||||
const timeout = setTimeout(() => {
|
|
||||||
clearInterval(dependencies);
|
|
||||||
initialization();
|
|
||||||
}, 5000);
|
|
||||||
|
|
||||||
function initialization() {
|
|
||||||
if (typeof core.connection === "undefined") {
|
|
||||||
// Not initialized
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @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 <arsen@mirzaev.sexy>
|
|
||||||
*/
|
|
||||||
core.connection = class connection {
|
|
||||||
// Wrap of indicator of the connection
|
|
||||||
static wrap = document.getElementById("connection");
|
|
||||||
|
|
||||||
// Indicator of the connection
|
|
||||||
static indicator = this.wrap.getElementsByTagName("i")[0];
|
|
||||||
|
|
||||||
// Description of the connection
|
|
||||||
static description = this.wrap.getElementsByTagName("small")[0];
|
|
||||||
|
|
||||||
// Statuc of the connection
|
|
||||||
static connected = false;
|
|
||||||
|
|
||||||
// Duration of the disconnected status
|
|
||||||
static timeout = 0;
|
|
||||||
|
|
||||||
// Instance of the time counter in disconnected status
|
|
||||||
static counter;
|
|
||||||
|
|
||||||
// Socket address (xn--e1ajlli это сокет)
|
|
||||||
static socket = "wss://arming.dev.mirzaev.sexy:9502";
|
|
||||||
|
|
||||||
// Instance of connection to the socket
|
|
||||||
static session;
|
|
||||||
|
|
||||||
// Iterval for reconnect
|
|
||||||
static interval;
|
|
||||||
|
|
||||||
// Attempts to connect (when core.connection.readyState === 0)
|
|
||||||
static attempts = 0;
|
|
||||||
|
|
||||||
// Interval for block
|
|
||||||
static block;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Initialize status of the connection to socket
|
|
||||||
*
|
|
||||||
* @param {bool} connected Connected?
|
|
||||||
*
|
|
||||||
* @return {void}
|
|
||||||
*/
|
|
||||||
static status(connected = false) {
|
|
||||||
if (this.indicator instanceof HTMLElement) {
|
|
||||||
// Initialized the indicator
|
|
||||||
|
|
||||||
if (this.connected = connected) {
|
|
||||||
// Connected
|
|
||||||
|
|
||||||
this.wrap.setAttribute("title", "Connected");
|
|
||||||
|
|
||||||
this.indicator.classList.remove("disconnected");
|
|
||||||
this.indicator.classList.add("connected");
|
|
||||||
|
|
||||||
clearInterval(this.counter);
|
|
||||||
this.description.innerText = "";
|
|
||||||
this.counter = undefined;
|
|
||||||
this.timeout = 0;
|
|
||||||
} else {
|
|
||||||
// Disconnected
|
|
||||||
|
|
||||||
this.wrap.setAttribute("title", "Disconnected");
|
|
||||||
|
|
||||||
this.indicator.classList.remove("connected");
|
|
||||||
this.indicator.classList.add("disconnected");
|
|
||||||
|
|
||||||
if (typeof this.counter === "undefined") {
|
|
||||||
this.counter = setInterval(() => {
|
|
||||||
this.timeout += 0.01;
|
|
||||||
this.description.innerText = this.timeout.toFixed(2);
|
|
||||||
}, 10);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Connect to the socket
|
|
||||||
*
|
|
||||||
* @param {bool|number} interval Connection check interval (ms)
|
|
||||||
* @param {function} preprocessing Will be executed every cycle
|
|
||||||
* @param {function} onmessage New message
|
|
||||||
* @param {function} onopen Connection opened
|
|
||||||
* @param {function} onclose Connection closed
|
|
||||||
* @param {function} onerror An error has occurred
|
|
||||||
*
|
|
||||||
* @return {Promise}
|
|
||||||
*/
|
|
||||||
static connect(
|
|
||||||
interval = false,
|
|
||||||
preprocessing,
|
|
||||||
onmessage,
|
|
||||||
onopen,
|
|
||||||
onclose,
|
|
||||||
onerror,
|
|
||||||
) {
|
|
||||||
return new Promise((resolve, reject) => {
|
|
||||||
try {
|
|
||||||
if (typeof interval === "number" && interval > 0) {
|
|
||||||
// Connect with automatic reconnect
|
|
||||||
|
|
||||||
if (typeof this.interval === "undefined") {
|
|
||||||
this.interval = setInterval(() => {
|
|
||||||
preprocessing();
|
|
||||||
|
|
||||||
if (
|
|
||||||
!(this.session instanceof WebSocket) ||
|
|
||||||
(this.session.readyState === 3 ||
|
|
||||||
this.session.readyState === 4) ||
|
|
||||||
(this.session.readyState === 0 &&
|
|
||||||
++this.attempts > 10)
|
|
||||||
) {
|
|
||||||
this.attempts = 0;
|
|
||||||
|
|
||||||
if (this.session instanceof WebSocket) {
|
|
||||||
this.session.close();
|
|
||||||
}
|
|
||||||
|
|
||||||
this.session = new WebSocket(this.socket);
|
|
||||||
this.session.addEventListener("message", (e) => {
|
|
||||||
try {
|
|
||||||
const json = JSON.parse(e.data);
|
|
||||||
|
|
||||||
if (json.type === "registration") {
|
|
||||||
// Подключение сокета к сессии
|
|
||||||
|
|
||||||
fetch("/socket/registration", {
|
|
||||||
method: "POST",
|
|
||||||
headers: {
|
|
||||||
"Content-Type":
|
|
||||||
"application/x-www-form-urlencoded",
|
|
||||||
},
|
|
||||||
body: `key=${json.key}`,
|
|
||||||
});
|
|
||||||
}
|
|
||||||
} catch (_e) {}
|
|
||||||
});
|
|
||||||
this.session.addEventListener("message", onmessage);
|
|
||||||
this.session.addEventListener("open", onopen);
|
|
||||||
this.session.addEventListener("close", onclose);
|
|
||||||
this.session.addEventListener("error", onerror);
|
|
||||||
|
|
||||||
resolve(this.session);
|
|
||||||
} else resolve(this.session);
|
|
||||||
}, interval);
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
// Connect without reconnecting
|
|
||||||
|
|
||||||
if (
|
|
||||||
!(this.session instanceof WebSocket) ||
|
|
||||||
(this.session.readyState === 3 ||
|
|
||||||
this.session.readyState === 4)
|
|
||||||
) {
|
|
||||||
if (this.session instanceof WebSocket) {
|
|
||||||
this.session.close();
|
|
||||||
}
|
|
||||||
|
|
||||||
this.session = new WebSocket(this.socket);
|
|
||||||
this.session.addEventListener("message", onmessage);
|
|
||||||
this.session.addEventListener("open", onopen);
|
|
||||||
this.session.addEventListener("close", onclose);
|
|
||||||
this.session.addEventListener("error", onerror);
|
|
||||||
|
|
||||||
resolve(this.session);
|
|
||||||
} else resolve(this.session);
|
|
||||||
}
|
|
||||||
} catch (_e) {}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Core is connected to the socket?
|
|
||||||
*
|
|
||||||
* @return {bool}
|
|
||||||
*/
|
|
||||||
static connected() {
|
|
||||||
return this.session instanceof WebSocket &&
|
|
||||||
this.session.readyState === 1;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
core.connection.connect(
|
|
||||||
3000,
|
|
||||||
() =>
|
|
||||||
core.connection.status(
|
|
||||||
core.connection.session instanceof WebSocket &&
|
|
||||||
core.connection.session.readyState === 1,
|
|
||||||
),
|
|
||||||
(e) => {
|
|
||||||
try {
|
|
||||||
const json = JSON.parse(e.data);
|
|
||||||
|
|
||||||
if (json.target === "task") {
|
|
||||||
// Заявка
|
|
||||||
|
|
||||||
// Инициализация строки
|
|
||||||
const row = document.getElementById(json._key);
|
|
||||||
|
|
||||||
if (row instanceof HTMLElement) {
|
|
||||||
// Инициализирована строка
|
|
||||||
|
|
||||||
if (json.type === "blocked") {
|
|
||||||
// Заблокирована заявка
|
|
||||||
|
|
||||||
// Запись статуса: "заблокирована"
|
|
||||||
row.setAttribute("data-blocked", json.account._key);
|
|
||||||
row.setAttribute(
|
|
||||||
"title",
|
|
||||||
"Редактирует: " + json.account.name,
|
|
||||||
);
|
|
||||||
|
|
||||||
// Удалить блокировку (60000 === 1 минута) (в базе данных стоит expires 1 минута тоже)
|
|
||||||
setTimeout(() => {
|
|
||||||
// Удаление статуса: "заблокирована"
|
|
||||||
row.removeAttribute("data-blocked");
|
|
||||||
row.removeAttribute("title");
|
|
||||||
|
|
||||||
// Обновление строки
|
|
||||||
tasks.row(row);
|
|
||||||
}, 60000);
|
|
||||||
} else if (json.type === "unblocked") {
|
|
||||||
// Разблокирована заявка
|
|
||||||
|
|
||||||
// Удаление статуса: "заблокирована"
|
|
||||||
row.removeAttribute("data-blocked");
|
|
||||||
row.removeAttribute("title");
|
|
||||||
|
|
||||||
// Обновление строки
|
|
||||||
tasks.row(row);
|
|
||||||
} else if (json.type === "updated") {
|
|
||||||
// Обновлена заявка
|
|
||||||
|
|
||||||
// Обновление строки
|
|
||||||
tasks.row(row);
|
|
||||||
} else if (json.type === "deleted") {
|
|
||||||
// Удалена заявка
|
|
||||||
|
|
||||||
// Удаление строки
|
|
||||||
row.remove();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} catch (_e) {}
|
|
||||||
// Инициализация идентифиатора
|
|
||||||
//const id = row.getAttribute("id");
|
|
||||||
|
|
||||||
// Инициализация количества непрочитанных сообщений
|
|
||||||
//const messages = row.lastElementChild.innerText;
|
|
||||||
|
|
||||||
// Инициализация статуса активной строки
|
|
||||||
//const selected = row.getAttribute("data-selected");
|
|
||||||
|
|
||||||
// Реинициализация строки
|
|
||||||
//row.outerHTML = data.rows;
|
|
||||||
|
|
||||||
// Реинициализация перезаписанной строки
|
|
||||||
//row = document.getElementById(id);
|
|
||||||
|
|
||||||
// Копирование статуса активной строки
|
|
||||||
//if (
|
|
||||||
// typeof selected === "string" &&
|
|
||||||
// selected === "true" &&
|
|
||||||
// document.body.contains(document.getElementById("popup"))
|
|
||||||
//) {
|
|
||||||
// row.setAttribute("data-selected", "true");
|
|
||||||
//}
|
|
||||||
},
|
|
||||||
(e) => {
|
|
||||||
//connection.status(
|
|
||||||
// core.connection instanceof WebSocket &&
|
|
||||||
// core.connection.readyState === 1,
|
|
||||||
//)
|
|
||||||
//console.log("Connected to WebSocket!");
|
|
||||||
},
|
|
||||||
(e) => {
|
|
||||||
//connection.status(
|
|
||||||
// core.connection instanceof WebSocket &&
|
|
||||||
// core.connection.readyState === 1,
|
|
||||||
//)
|
|
||||||
//console.log("Connection closed");
|
|
||||||
},
|
|
||||||
(e) => {
|
|
||||||
//console.log("Error happens");
|
|
||||||
},
|
|
||||||
);
|
|
||||||
}
|
|
||||||
})
|
|
||||||
);
|
|
|
@ -1,5 +1,3 @@
|
||||||
"use strict";
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @name Core
|
* @name Core
|
||||||
*
|
*
|
||||||
|
@ -9,7 +7,7 @@
|
||||||
* @license http://www.wtfpl.net/ Do What The Fuck You Want To Public License
|
* @license http://www.wtfpl.net/ Do What The Fuck You Want To Public License
|
||||||
* @author Arsen Mirzaev Tatyano-Muradovich <arsen@mirzaev.sexy>
|
* @author Arsen Mirzaev Tatyano-Muradovich <arsen@mirzaev.sexy>
|
||||||
*/
|
*/
|
||||||
const core = class core {
|
class core {
|
||||||
// Domain
|
// Domain
|
||||||
static domain = window.location.hostname;
|
static domain = window.location.hostname;
|
||||||
|
|
||||||
|
@ -66,31 +64,51 @@ const core = class core {
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Buffer
|
* @name Modules
|
||||||
|
*
|
||||||
|
* @method connect(modules) Connect modules
|
||||||
|
*
|
||||||
|
* @return {Array} List of initialized modules
|
||||||
|
*/
|
||||||
|
static modules() {
|
||||||
|
return Object.keys(this).filter((module) =>
|
||||||
|
this[module]?.type === "module"
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @name Buffer
|
||||||
*/
|
*/
|
||||||
static buffer = class buffer {
|
static buffer = class buffer {
|
||||||
/**
|
/**
|
||||||
* Write to buffers
|
* @name Write to buffers
|
||||||
|
*
|
||||||
|
* @description
|
||||||
|
* Write to buffers (interface)
|
||||||
*
|
*
|
||||||
* @param {string} name Name of the parameter
|
* @param {string} name Name of the parameter
|
||||||
* @param {string} value Value of the parameter (it can be JSON)
|
* @param {string} value Value of the parameter (it can be JSON)
|
||||||
*
|
*
|
||||||
* @return {void}
|
* @return {bool} Execution completed with an error?
|
||||||
*/
|
*/
|
||||||
static write(name, value) {
|
static write(name, value) {
|
||||||
if (typeof this.session === "function") {
|
core.modules.connect("damper").then(
|
||||||
// Initialized the session implement object
|
() => {
|
||||||
|
// Imported the damper module
|
||||||
|
|
||||||
// Write to the session buffer
|
// Execute under damper
|
||||||
core.session.buffer.write(name, value);
|
this.write.damper(name, value);
|
||||||
}
|
},
|
||||||
|
() => {
|
||||||
|
// Not imported the damper module
|
||||||
|
|
||||||
if (typeof this.account === "function") {
|
// Execute
|
||||||
// Initialized the account implement object
|
this.write.system(name, value);
|
||||||
|
},
|
||||||
|
);
|
||||||
|
|
||||||
// Write to the account buffer
|
// Exit (success)
|
||||||
core.account.buffer.write(name, value);
|
return false;
|
||||||
}
|
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -274,4 +292,112 @@ const core = class core {
|
||||||
},
|
},
|
||||||
300,
|
300,
|
||||||
); */
|
); */
|
||||||
};
|
}
|
||||||
|
|
||||||
|
Object.assign(
|
||||||
|
core.modules,
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* @name Connect modules
|
||||||
|
*
|
||||||
|
* @param {Array|string} modules Names of modules or name of the module
|
||||||
|
*
|
||||||
|
* @return {Prommise}
|
||||||
|
*/
|
||||||
|
async connect(modules) {
|
||||||
|
// Normalisation required argiments
|
||||||
|
if (typeof modules === "string") modules = [modules];
|
||||||
|
|
||||||
|
if (modules instanceof Array) {
|
||||||
|
// Received and validated required arguments
|
||||||
|
|
||||||
|
// Initializing the registry of loaded modules
|
||||||
|
const loaded = [];
|
||||||
|
|
||||||
|
for (const module of modules) {
|
||||||
|
// Iterating over modules
|
||||||
|
|
||||||
|
// Downloading, importing and writing the module into a core property and into registry of loaded modules
|
||||||
|
core[module] =
|
||||||
|
loaded[module] =
|
||||||
|
await (await import(`./modules/${module}.js`)).default;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Exit (success)
|
||||||
|
return loaded;
|
||||||
|
}
|
||||||
|
},
|
||||||
|
},
|
||||||
|
);
|
||||||
|
|
||||||
|
core.modules.connect("damper").then(() => {
|
||||||
|
// Imported the damper module
|
||||||
|
|
||||||
|
Object.assign(
|
||||||
|
core.buffer.write,
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* @name Write to buffers
|
||||||
|
*
|
||||||
|
* @description
|
||||||
|
* Write to buffers (damper)
|
||||||
|
*
|
||||||
|
* @param {string} name Name of the parameter
|
||||||
|
* @param {string} value Value of the parameter (it can be JSON)
|
||||||
|
* @param {bool} force Ignore the damper? (false)
|
||||||
|
*
|
||||||
|
* @return {Promise}
|
||||||
|
*/
|
||||||
|
damper: core.damper(
|
||||||
|
(...variables) => core.buffer.write.system(...variables),
|
||||||
|
300,
|
||||||
|
3,
|
||||||
|
),
|
||||||
|
},
|
||||||
|
);
|
||||||
|
});
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @name Write to buffers
|
||||||
|
*
|
||||||
|
* @description
|
||||||
|
* Write to buffers (system)
|
||||||
|
*
|
||||||
|
* @param {string} name Name of the parameter
|
||||||
|
* @param {string} value Value of the parameter (it can be JSON)
|
||||||
|
*
|
||||||
|
* @return {Promise}
|
||||||
|
*/
|
||||||
|
Object.assign(
|
||||||
|
core.buffer.write,
|
||||||
|
{
|
||||||
|
system(
|
||||||
|
name,
|
||||||
|
value,
|
||||||
|
resolve = () => {},
|
||||||
|
reject = () => {},
|
||||||
|
) {
|
||||||
|
try {
|
||||||
|
core.modules.connect("session").then(() => {
|
||||||
|
// Imported the session module
|
||||||
|
|
||||||
|
// Write to the session buffer
|
||||||
|
session.default.buffer?.write(name, value);
|
||||||
|
});
|
||||||
|
|
||||||
|
core.modules.connect("account").then(() => {
|
||||||
|
// Imported the account module
|
||||||
|
|
||||||
|
// Write to the account buffer
|
||||||
|
account.default.buffer?.write(name, value);
|
||||||
|
});
|
||||||
|
|
||||||
|
// Exit (success)
|
||||||
|
resolve();
|
||||||
|
} catch (e) {
|
||||||
|
// Exit (fail)
|
||||||
|
reject(e);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
},
|
||||||
|
);
|
||||||
|
|
|
@ -1,96 +0,0 @@
|
||||||
"use strict";
|
|
||||||
|
|
||||||
// Import dependencies
|
|
||||||
import("/js/core.js").then(() => {
|
|
||||||
const dependencies = setInterval(() => {
|
|
||||||
if (typeof core === "function") {
|
|
||||||
clearInterval(dependencies);
|
|
||||||
clearTimeout(timeout);
|
|
||||||
initialization();
|
|
||||||
}
|
|
||||||
}, 10);
|
|
||||||
const timeout = setTimeout(() => {
|
|
||||||
clearInterval(dependencies);
|
|
||||||
initialization();
|
|
||||||
}, 5000);
|
|
||||||
|
|
||||||
function initialization() {
|
|
||||||
if (typeof core.damper === "undefined") {
|
|
||||||
// Not initialized
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @name Damper
|
|
||||||
*
|
|
||||||
* @description
|
|
||||||
* Execute multiple "function" calls in a "timeout" amount of time just once
|
|
||||||
*
|
|
||||||
* @param {function} function Function to execute after damping
|
|
||||||
* @param {number} timeout Timer in milliseconds (ms)
|
|
||||||
* @param {number} force Argument number storing the status of enforcement execution (see @example)
|
|
||||||
*
|
|
||||||
* @return {Promise}
|
|
||||||
*
|
|
||||||
* @memberof core
|
|
||||||
*
|
|
||||||
* @example
|
|
||||||
* a = damper(
|
|
||||||
* async (
|
|
||||||
* a, // 0
|
|
||||||
* b, // 1
|
|
||||||
* c, // 2
|
|
||||||
* force = false, // 3
|
|
||||||
* d, // 4
|
|
||||||
* resolve,
|
|
||||||
* reject
|
|
||||||
* ) => {
|
|
||||||
* // Body of the function
|
|
||||||
*
|
|
||||||
* resolve();
|
|
||||||
* },
|
|
||||||
* 500,
|
|
||||||
* 3, // 3 -> "force" argument
|
|
||||||
* );
|
|
||||||
*
|
|
||||||
* a('for a', 'for b', 'for c', true, 'for d'); // Force execute is enabled
|
|
||||||
*
|
|
||||||
* @license http://www.wtfpl.net/ Do What The Fuck You Want To Public License
|
|
||||||
* @author Arsen Mirzaev Tatyano-Muradovich <arsen@mirzaev.sexy>
|
|
||||||
*/
|
|
||||||
core.damper = (func, timeout = 300, force) => {
|
|
||||||
// Declaring of the timer for executing the function
|
|
||||||
let timer;
|
|
||||||
|
|
||||||
return ((...args) => {
|
|
||||||
return new Promise((resolve, reject) => {
|
|
||||||
// Deinitializing of the timer
|
|
||||||
clearTimeout(timer);
|
|
||||||
|
|
||||||
if (typeof force === "number" && args[force]) {
|
|
||||||
// Requested execution with ignoring the timer
|
|
||||||
|
|
||||||
// Deleting the force argument
|
|
||||||
if (typeof force === "number") delete args[force - 1];
|
|
||||||
|
|
||||||
// Writing promise handlers into the arguments variable
|
|
||||||
args.push(resolve, reject);
|
|
||||||
|
|
||||||
// Executing the function
|
|
||||||
func.apply(this, args);
|
|
||||||
} else {
|
|
||||||
// Normal execution
|
|
||||||
|
|
||||||
// Deleting the force argument
|
|
||||||
if (typeof force === "number") delete args[force - 1];
|
|
||||||
|
|
||||||
// Writing promise handlers into the arguments variable
|
|
||||||
args.push(resolve, reject);
|
|
||||||
|
|
||||||
// Resetting the timer and executing the function when the timer expires
|
|
||||||
timer = setTimeout(() => func.apply(this, args), timeout);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
});
|
|
||||||
};
|
|
||||||
}
|
|
||||||
}
|
|
||||||
});
|
|
|
@ -1,23 +1,5 @@
|
||||||
"use strict";
|
"use strict";
|
||||||
|
|
||||||
// Import dependencies
|
|
||||||
import("/js/core.js").then(() => {
|
|
||||||
const dependencies = setInterval(() => {
|
|
||||||
if (typeof core === "function") {
|
|
||||||
clearInterval(dependencies);
|
|
||||||
clearTimeout(timeout);
|
|
||||||
initialization();
|
|
||||||
}
|
|
||||||
}, 10);
|
|
||||||
const timeout = setTimeout(() => {
|
|
||||||
clearInterval(dependencies);
|
|
||||||
initialization();
|
|
||||||
}, 5000);
|
|
||||||
|
|
||||||
function initialization() {
|
|
||||||
if (typeof core.hotline === "undefined") {
|
|
||||||
// Not initialized
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @name Бегущая строка
|
* @name Бегущая строка
|
||||||
*
|
*
|
||||||
|
@ -31,8 +13,6 @@ import("/js/core.js").then(() => {
|
||||||
* события при выбранных действиях для того, чтобы пользователь имел возможность
|
* события при выбранных действиях для того, чтобы пользователь имел возможность
|
||||||
* дорабатывать функционал без изучения и изменения моего кода
|
* дорабатывать функционал без изучения и изменения моего кода
|
||||||
*
|
*
|
||||||
* @memberof core
|
|
||||||
*
|
|
||||||
* @example
|
* @example
|
||||||
* сonst hotline = new hotline();
|
* сonst hotline = new hotline();
|
||||||
* hotline.step = '-5';
|
* hotline.step = '-5';
|
||||||
|
@ -46,7 +26,7 @@ import("/js/core.js").then(() => {
|
||||||
* @license http://www.wtfpl.net/ Do What The Fuck You Want To Public License
|
* @license http://www.wtfpl.net/ Do What The Fuck You Want To Public License
|
||||||
* @author Arsen Mirzaev Tatyano-Muradovich <arsen@mirzaev.sexy>
|
* @author Arsen Mirzaev Tatyano-Muradovich <arsen@mirzaev.sexy>
|
||||||
*/
|
*/
|
||||||
core.hotline = class hotline {
|
export default class hotline {
|
||||||
// Идентификатор
|
// Идентификатор
|
||||||
#id = 0;
|
#id = 0;
|
||||||
|
|
||||||
|
@ -257,14 +237,14 @@ import("/js/core.js").then(() => {
|
||||||
// Вертикальная бегущая строка
|
// Вертикальная бегущая строка
|
||||||
|
|
||||||
// Удаление отступов (движения)
|
// Удаление отступов (движения)
|
||||||
_this.#shell.lastElementChild.style.marginTop =
|
_this.#shell.lastElementChild.style.marginTop = -coords.height -
|
||||||
-coords.height - separator + "px";
|
separator + "px";
|
||||||
} else {
|
} else {
|
||||||
// Горизонтальная бегущая строка
|
// Горизонтальная бегущая строка
|
||||||
|
|
||||||
// Удаление отступов (движения)
|
// Удаление отступов (движения)
|
||||||
_this.#shell.lastElementChild.style.marginLeft =
|
_this.#shell.lastElementChild.style.marginLeft = -coords.width -
|
||||||
-coords.width - separator + "px";
|
separator + "px";
|
||||||
}
|
}
|
||||||
|
|
||||||
// Копирование последнего элемента в начало строки
|
// Копирование последнего элемента в начало строки
|
||||||
|
@ -286,8 +266,7 @@ import("/js/core.js").then(() => {
|
||||||
new CustomEvent(`hotline.${_this.#id}.transfer.start`, {
|
new CustomEvent(`hotline.${_this.#id}.transfer.start`, {
|
||||||
detail: {
|
detail: {
|
||||||
element: _this.#shell.lastElementChild,
|
element: _this.#shell.lastElementChild,
|
||||||
offset:
|
offset: (_this.vertical ? coords.height : coords.width) +
|
||||||
(_this.vertical ? coords.height : coords.width) +
|
|
||||||
separator,
|
separator,
|
||||||
},
|
},
|
||||||
}),
|
}),
|
||||||
|
@ -434,8 +413,7 @@ import("/js/core.js").then(() => {
|
||||||
const to = _y - (y + offset - first.offset);
|
const to = _y - (y + offset - first.offset);
|
||||||
|
|
||||||
// Движение
|
// Движение
|
||||||
_this.#shell.firstElementChild.style.marginTop =
|
_this.#shell.firstElementChild.style.marginTop = to +
|
||||||
to +
|
|
||||||
"px";
|
"px";
|
||||||
} else {
|
} else {
|
||||||
// Горизонтальная бегущая строка
|
// Горизонтальная бегущая строка
|
||||||
|
@ -446,8 +424,7 @@ import("/js/core.js").then(() => {
|
||||||
const to = _x - (x + offset - first.offset);
|
const to = _x - (x + offset - first.offset);
|
||||||
|
|
||||||
// Движение
|
// Движение
|
||||||
_this.#shell.firstElementChild.style.marginLeft =
|
_this.#shell.firstElementChild.style.marginLeft = to +
|
||||||
to +
|
|
||||||
"px";
|
"px";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -673,8 +650,7 @@ import("/js/core.js").then(() => {
|
||||||
|
|
||||||
configure(attribute) {
|
configure(attribute) {
|
||||||
// Инициализация названия параметра
|
// Инициализация названия параметра
|
||||||
const parameter =
|
const parameter = (/^data-hotline-(\w+)$/.exec(attribute) ?? [, null])[1];
|
||||||
(/^data-hotline-(\w+)$/.exec(attribute) ?? [, null])[1];
|
|
||||||
|
|
||||||
if (typeof parameter === "string") {
|
if (typeof parameter === "string") {
|
||||||
// Параметр найден
|
// Параметр найден
|
||||||
|
@ -771,7 +747,4 @@ import("/js/core.js").then(() => {
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
|
||||||
}
|
}
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
|
@ -1,265 +0,0 @@
|
||||||
"use strict";
|
|
||||||
|
|
||||||
// Import dependencies
|
|
||||||
import("/js/core.js").then(() =>
|
|
||||||
import("/js/damper.js").then(() => {
|
|
||||||
const dependencies = setInterval(() => {
|
|
||||||
if (typeof core === "function" && typeof core.damper === "function") {
|
|
||||||
clearInterval(dependencies);
|
|
||||||
clearTimeout(timeout);
|
|
||||||
initialization();
|
|
||||||
}
|
|
||||||
}, 10);
|
|
||||||
const timeout = setTimeout(() => {
|
|
||||||
clearInterval(dependencies);
|
|
||||||
initialization();
|
|
||||||
}, 5000);
|
|
||||||
|
|
||||||
function initialization() {
|
|
||||||
if (typeof core.loader === "undefined") {
|
|
||||||
// Not initialized
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @name Loader
|
|
||||||
*
|
|
||||||
* @description
|
|
||||||
* Implements actions with loading and rendering content
|
|
||||||
*
|
|
||||||
* @memberof core
|
|
||||||
*
|
|
||||||
* @license http://www.wtfpl.net/ Do What The Fuck You Want To Public License
|
|
||||||
* @author Arsen Mirzaev Tatyano-Muradovich <arsen@mirzaev.sexy>
|
|
||||||
*/
|
|
||||||
core.loader = class loader {
|
|
||||||
/**
|
|
||||||
* Load
|
|
||||||
*
|
|
||||||
* @param {string} uri
|
|
||||||
* @param {string} body
|
|
||||||
*
|
|
||||||
* @return {Promise}
|
|
||||||
*/
|
|
||||||
static async load(uri = "/", body) {
|
|
||||||
if (typeof uri === "string") {
|
|
||||||
// Received and validated uri
|
|
||||||
|
|
||||||
return await core
|
|
||||||
.request(
|
|
||||||
uri,
|
|
||||||
body,
|
|
||||||
"POST",
|
|
||||||
{
|
|
||||||
"Content-Type": "application/x-www-form-urlencoded",
|
|
||||||
Accept: "application/json",
|
|
||||||
},
|
|
||||||
"json"
|
|
||||||
)
|
|
||||||
.then((json) => {
|
|
||||||
if (
|
|
||||||
json.errors !== null &&
|
|
||||||
typeof json.errors === "object" &&
|
|
||||||
json.errors.length > 0
|
|
||||||
) {
|
|
||||||
// Fail (received errors)
|
|
||||||
} else {
|
|
||||||
// Success (not received errors)
|
|
||||||
|
|
||||||
// Writing to the browser history
|
|
||||||
history.pushState({}, json.title ?? uri, uri);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* The <title>
|
|
||||||
*
|
|
||||||
* The title of the page
|
|
||||||
*/
|
|
||||||
if (
|
|
||||||
typeof json.title === "string" &&
|
|
||||||
json.title.length > 0
|
|
||||||
) {
|
|
||||||
// Received text for the <title> of the page
|
|
||||||
|
|
||||||
// Search for the <title> element (document.title)
|
|
||||||
const title = document.getElementsByTagName("title")[0];
|
|
||||||
|
|
||||||
if (title instanceof HTMLElement) {
|
|
||||||
// Found the <title> element
|
|
||||||
|
|
||||||
// Writing into the <title> element
|
|
||||||
title.innerText = json.title;
|
|
||||||
} else {
|
|
||||||
// Not found the <title> element
|
|
||||||
|
|
||||||
// Initialize the <title> element
|
|
||||||
const title = document.createElement("title");
|
|
||||||
|
|
||||||
// Inititalize the <head> element (document.head)
|
|
||||||
const head = document.getElementsByTagName("head")[0];
|
|
||||||
|
|
||||||
if (head instanceof HTMLElement) {
|
|
||||||
// Found the <head> element
|
|
||||||
|
|
||||||
// Writing the <title> element into the <head> element
|
|
||||||
head.appendChild(title);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Writing title into the <title> element
|
|
||||||
title.innerText = json.title;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* The <header> element
|
|
||||||
*/
|
|
||||||
if (
|
|
||||||
typeof json.header === "string" &&
|
|
||||||
json.header.length > 0
|
|
||||||
) {
|
|
||||||
// Received and validated the header HTML-code
|
|
||||||
|
|
||||||
if (core.header instanceof HTMLElement) {
|
|
||||||
// Found the <header> element
|
|
||||||
|
|
||||||
// Writing into the <header> element
|
|
||||||
core.header.outerHTML = json.header;
|
|
||||||
|
|
||||||
// Reinitializing the parameter with the <header> element
|
|
||||||
core.header =
|
|
||||||
document.getElementsByTagName("header")[0];
|
|
||||||
} else {
|
|
||||||
// Not found the <header> element
|
|
||||||
|
|
||||||
// Initialize the <header> element
|
|
||||||
core.header = document.createElement("header");
|
|
||||||
|
|
||||||
// Inititalize the <body> element (document.body)
|
|
||||||
const body = document.getElementsByTagName("body")[0];
|
|
||||||
|
|
||||||
if (body instanceof HTMLElement) {
|
|
||||||
// Found the <body> element
|
|
||||||
|
|
||||||
if (core.main instanceof HTMLElement) {
|
|
||||||
// Found the <main> element
|
|
||||||
|
|
||||||
// Writing the <header> element before the <main> element
|
|
||||||
body.insertBefore(core.header, core.main);
|
|
||||||
} else if (core.footer instanceof HTMLElement) {
|
|
||||||
// Fount the <footer> element
|
|
||||||
|
|
||||||
// Writing the <header> element before the <footer> element
|
|
||||||
body.insertBefore(core.header, core.footer);
|
|
||||||
} else {
|
|
||||||
// Not found the <main> element and the <footer> element
|
|
||||||
|
|
||||||
// Search for the last <section> element inside the <body> element
|
|
||||||
const section = document.body.querySelector(
|
|
||||||
"body > section:last-of-type"
|
|
||||||
);
|
|
||||||
|
|
||||||
if (section instanceof HTMLElement) {
|
|
||||||
// Found the last <section> element inside the <body> element
|
|
||||||
|
|
||||||
// Writing the <header> element after the last <section> element inside the <body> element
|
|
||||||
body.insertBefore(
|
|
||||||
core.header,
|
|
||||||
section.nextSibling
|
|
||||||
);
|
|
||||||
} else {
|
|
||||||
// Not found section elements <section> inside the <body> element
|
|
||||||
|
|
||||||
// Writing the <header> element into the <body> element
|
|
||||||
body.appendChild(core.header);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Writing into the <header> element
|
|
||||||
core.header.outerHTML = json.header;
|
|
||||||
|
|
||||||
// Reinitializing the parameter with the <header> element
|
|
||||||
core.header =
|
|
||||||
document.getElementsByTagName("header")[0];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* The <main> element
|
|
||||||
*
|
|
||||||
* The main content of the page
|
|
||||||
*/
|
|
||||||
if (typeof json.main === "string" && json.main.length > 0) {
|
|
||||||
// Received and validated the <main> HTML-code
|
|
||||||
|
|
||||||
if (core.main instanceof HTMLElement) {
|
|
||||||
// Found the <main> element
|
|
||||||
|
|
||||||
// Writing into the <main> element
|
|
||||||
core.main.outerHTML = json.main;
|
|
||||||
|
|
||||||
// Reinitializing the parameter with the <main> element
|
|
||||||
core.main = document.getElementsByTagName("main")[0];
|
|
||||||
} else {
|
|
||||||
// Not found the <main> element
|
|
||||||
|
|
||||||
// Initialize the <main> element
|
|
||||||
core.main = document.createElement("main");
|
|
||||||
|
|
||||||
// Inititalize the <body> element (document.body)
|
|
||||||
const body = document.getElementsByTagName("body")[0];
|
|
||||||
|
|
||||||
if (body instanceof HTMLElement) {
|
|
||||||
// Found the <body> element
|
|
||||||
|
|
||||||
if (core.header instanceof HTMLElement) {
|
|
||||||
// Found the <header> element
|
|
||||||
|
|
||||||
// Writing the <main> element after the <header> element
|
|
||||||
body.insertBefore(
|
|
||||||
core.main,
|
|
||||||
core.header.nextSibling
|
|
||||||
);
|
|
||||||
} else if (core.footer instanceof HTMLElement) {
|
|
||||||
// Fount the <footer> element
|
|
||||||
|
|
||||||
// Writing the <main> element before the <footer> element
|
|
||||||
body.insertBefore(core.main, core.footer);
|
|
||||||
} else {
|
|
||||||
// Not found the <header> element and the <footer> element
|
|
||||||
|
|
||||||
// Search for the last <section> element inside the <body> element
|
|
||||||
const section = document.body.querySelector(
|
|
||||||
"body > section:last-of-type"
|
|
||||||
);
|
|
||||||
|
|
||||||
if (section instanceof HTMLElement) {
|
|
||||||
// Found the last <section> element inside the <body> element
|
|
||||||
|
|
||||||
// Writing the <main> element after the last <section> element inside the <body> element
|
|
||||||
body.insertBefore(core.main, section.nextSibling);
|
|
||||||
} else {
|
|
||||||
// Not found section elements <section> inside the <body> element
|
|
||||||
|
|
||||||
// Writing the <main> element into the <body> element
|
|
||||||
body.appendChild(core.main);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Writing into the <main> element
|
|
||||||
core.main.outerHTML = json.main;
|
|
||||||
|
|
||||||
// Reinitializing the parameter with the <main> element
|
|
||||||
core.main = document.getElementsByTagName("main")[0];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Exit (success)
|
|
||||||
return json;
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
|
||||||
}
|
|
||||||
}
|
|
||||||
})
|
|
||||||
);
|
|
|
@ -0,0 +1,202 @@
|
||||||
|
"use strict";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @name Account
|
||||||
|
*
|
||||||
|
* @description
|
||||||
|
* Implements actions with accounts
|
||||||
|
*
|
||||||
|
* @license http://www.wtfpl.net/ Do What The Fuck You Want To Public License
|
||||||
|
* @author Arsen Mirzaev Tatyano-Muradovich <arsen@mirzaev.sexy>
|
||||||
|
*/
|
||||||
|
export default class account {
|
||||||
|
/**
|
||||||
|
* @name Type of the program
|
||||||
|
*/
|
||||||
|
static type = "module";
|
||||||
|
|
||||||
|
// Wrap of indicator of the account
|
||||||
|
static wrap = document.getElementById("account");
|
||||||
|
|
||||||
|
// Indicator of the account
|
||||||
|
static indicator = this.wrap?.getElementsByTagName("i")[0] ?? null;
|
||||||
|
|
||||||
|
// Description of the account
|
||||||
|
static description = this.wrap?.getElementsByTagName("small")[0] ?? null;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Authentication
|
||||||
|
*
|
||||||
|
* @return {void}
|
||||||
|
*/
|
||||||
|
static authentication() {
|
||||||
|
core.status_loading.removeAttribute("disabled");
|
||||||
|
|
||||||
|
const timer_for_response = setTimeout(() => {
|
||||||
|
core.status_loading.setAttribute("disabled", true);
|
||||||
|
}, 3000);
|
||||||
|
|
||||||
|
core.modules.connect("telegram").then(() => {
|
||||||
|
// Imported the telegram module
|
||||||
|
|
||||||
|
if (core.telegram.api.initData.length > 0) {
|
||||||
|
core
|
||||||
|
.request(
|
||||||
|
"/session/connect/telegram",
|
||||||
|
core.telegram.api.initData,
|
||||||
|
)
|
||||||
|
.then((json) => {
|
||||||
|
if (json) {
|
||||||
|
// Received a JSON-response
|
||||||
|
|
||||||
|
if (
|
||||||
|
json.errors !== null &&
|
||||||
|
typeof json.errors === "object" &&
|
||||||
|
json.errors.length > 0
|
||||||
|
) {
|
||||||
|
// Errors received
|
||||||
|
} else {
|
||||||
|
// Errors not received
|
||||||
|
|
||||||
|
if (json.connected === true) {
|
||||||
|
core.status_loading.setAttribute("disabled", true);
|
||||||
|
clearTimeout(timer_for_response);
|
||||||
|
|
||||||
|
const a = core.status_account.getElementsByTagName("a")[0];
|
||||||
|
a.setAttribute("onclick", "core.account.profile()");
|
||||||
|
a.innerText = json.domain.length > 0
|
||||||
|
? "@" + json.domain
|
||||||
|
: "ERROR";
|
||||||
|
}
|
||||||
|
|
||||||
|
if (
|
||||||
|
json.language !== null &&
|
||||||
|
typeof json.language === "string" &&
|
||||||
|
json.langiage.length === 2
|
||||||
|
) {
|
||||||
|
core.language = json.language;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @name Buffer
|
||||||
|
*/
|
||||||
|
static buffer = class buffer {
|
||||||
|
/**
|
||||||
|
* @name Write
|
||||||
|
*
|
||||||
|
* @description
|
||||||
|
* Write to the account buffer (interface)
|
||||||
|
*
|
||||||
|
* @param {string} name Name of the parameter
|
||||||
|
* @param {string} value Value of the parameter (it can be JSON)
|
||||||
|
* @param {bool} force Ignore the damper? (false)
|
||||||
|
*
|
||||||
|
* @return {bool} Execution completed with an error?
|
||||||
|
*/
|
||||||
|
static write = (name, value, force = false) => {
|
||||||
|
core.modules.connect("damper").then(
|
||||||
|
() => {
|
||||||
|
// Imported the damper module
|
||||||
|
|
||||||
|
// Execute under damper
|
||||||
|
this.write.damper(name, value, force);
|
||||||
|
},
|
||||||
|
() => {
|
||||||
|
// Not imported the damper module
|
||||||
|
|
||||||
|
// Execute
|
||||||
|
this.write.system(name, value, force);
|
||||||
|
},
|
||||||
|
);
|
||||||
|
|
||||||
|
// Exit (success)
|
||||||
|
return false;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
core.modules.connect("damper").then(() => {
|
||||||
|
// Imported the damper module
|
||||||
|
|
||||||
|
Object.assign(
|
||||||
|
account.buffer.write,
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* @name Write
|
||||||
|
*
|
||||||
|
* @description
|
||||||
|
* Write to the account buffer (damper)
|
||||||
|
*
|
||||||
|
* @param {string} name Name of the parameter
|
||||||
|
* @param {string} value Value of the parameter (it can be JSON)
|
||||||
|
* @param {bool} force Ignore the damper? (false)
|
||||||
|
*
|
||||||
|
* @return {Promise}
|
||||||
|
*/
|
||||||
|
damper: core.damper(
|
||||||
|
(...variables) => account.buffer.write.system(...variables),
|
||||||
|
300,
|
||||||
|
3,
|
||||||
|
),
|
||||||
|
},
|
||||||
|
);
|
||||||
|
});
|
||||||
|
|
||||||
|
Object.assign(
|
||||||
|
account.buffer.write,
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* @name Write
|
||||||
|
*
|
||||||
|
* @description
|
||||||
|
* Write to the account buffer (system)
|
||||||
|
*
|
||||||
|
* @param {string} name Name of the parameter
|
||||||
|
* @param {string} value Value of the parameter (it can be JSON)
|
||||||
|
*
|
||||||
|
* @return {Promise}
|
||||||
|
*/
|
||||||
|
async system(
|
||||||
|
name,
|
||||||
|
value,
|
||||||
|
resolve = () => {},
|
||||||
|
reject = () => {},
|
||||||
|
) {
|
||||||
|
try {
|
||||||
|
if (typeof name === "string" && typeof value === "string") {
|
||||||
|
// Received and validated required arguments
|
||||||
|
|
||||||
|
// Sending request to the server
|
||||||
|
return await core.request(
|
||||||
|
"/account/write",
|
||||||
|
`${name}=${value}`,
|
||||||
|
"POST",
|
||||||
|
)
|
||||||
|
.then(
|
||||||
|
(json) => {
|
||||||
|
if (json) {
|
||||||
|
// Received a JSON-response
|
||||||
|
|
||||||
|
// Exit (success)
|
||||||
|
resolve(json);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
() => reject(),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
} catch (e) {
|
||||||
|
// Exit (fail)
|
||||||
|
reject(e);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
},
|
||||||
|
);
|
||||||
|
|
||||||
|
// Connecting to the core
|
||||||
|
if (!core.account) core.account = account;
|
|
@ -0,0 +1,528 @@
|
||||||
|
"use strict";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @name Cart
|
||||||
|
*
|
||||||
|
* @description
|
||||||
|
* Implements actions with cart
|
||||||
|
*
|
||||||
|
* @license http://www.wtfpl.net/ Do What The Fuck You Want To Public License
|
||||||
|
* @author Arsen Mirzaev Tatyano-Muradovich <arsen@mirzaev.sexy>
|
||||||
|
*/
|
||||||
|
export default class cart {
|
||||||
|
/**
|
||||||
|
* @name Type of the program
|
||||||
|
*/
|
||||||
|
static type = "module";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Toggle
|
||||||
|
*
|
||||||
|
* Toggle the product in the cart (interface)
|
||||||
|
*
|
||||||
|
* @param {HTMLButtonElement|HTMLInputElement} element Handler elememnt of the product
|
||||||
|
* @param {HTMLElement} product The product element
|
||||||
|
* @param {bool} remove Remove the product element if json.amount === 0?
|
||||||
|
* @param {bool} force Ignore the damper? (false)
|
||||||
|
*
|
||||||
|
* @return {bool} Execution completed with an error?
|
||||||
|
*/
|
||||||
|
static toggle(element, product, remove = false, force = false) {
|
||||||
|
// Blocking the element
|
||||||
|
element.setAttribute("disabled", "true");
|
||||||
|
|
||||||
|
core.modules.connect("damper").then(
|
||||||
|
() => {
|
||||||
|
// Imported the damper module
|
||||||
|
|
||||||
|
// Execute under damper
|
||||||
|
this.product.damper(
|
||||||
|
element,
|
||||||
|
product,
|
||||||
|
"toggle",
|
||||||
|
undefined,
|
||||||
|
remove,
|
||||||
|
force,
|
||||||
|
);
|
||||||
|
},
|
||||||
|
() => {
|
||||||
|
// Not imported the damper module
|
||||||
|
|
||||||
|
// Execute
|
||||||
|
this.product.system(
|
||||||
|
element,
|
||||||
|
product,
|
||||||
|
"toggle",
|
||||||
|
undefined,
|
||||||
|
remove,
|
||||||
|
force,
|
||||||
|
);
|
||||||
|
},
|
||||||
|
);
|
||||||
|
|
||||||
|
// Exit (success)
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Write
|
||||||
|
*
|
||||||
|
* Write the product in the cart (interface)
|
||||||
|
*
|
||||||
|
* @param {HTMLButtonElement|HTMLInputElement} element Handler elememnt of the product
|
||||||
|
* @param {HTMLElement} product The product element
|
||||||
|
* @param {number} amount Amount of writings
|
||||||
|
* @param {bool} remove Remove the product element if json.amount === 0?
|
||||||
|
* @param {bool} force Ignore the damper? (false)
|
||||||
|
*
|
||||||
|
* @return {bool} Execution completed with an error?
|
||||||
|
*/
|
||||||
|
static write(
|
||||||
|
element,
|
||||||
|
product,
|
||||||
|
amount = 1,
|
||||||
|
remove = false,
|
||||||
|
force = false,
|
||||||
|
) {
|
||||||
|
// Blocking the element
|
||||||
|
element.setAttribute("disabled", "true");
|
||||||
|
|
||||||
|
core.modules.connect("damper").then(
|
||||||
|
() => {
|
||||||
|
// Imported the damper module
|
||||||
|
|
||||||
|
// Execute under damper
|
||||||
|
this.product.damper(
|
||||||
|
element,
|
||||||
|
product,
|
||||||
|
"write",
|
||||||
|
amount,
|
||||||
|
remove,
|
||||||
|
force,
|
||||||
|
);
|
||||||
|
},
|
||||||
|
() => {
|
||||||
|
// Not imported the damper module
|
||||||
|
|
||||||
|
// Execute
|
||||||
|
this.product.system(
|
||||||
|
element,
|
||||||
|
product,
|
||||||
|
"write",
|
||||||
|
amount,
|
||||||
|
remove,
|
||||||
|
force,
|
||||||
|
);
|
||||||
|
},
|
||||||
|
);
|
||||||
|
|
||||||
|
// Exit (success)
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Delete
|
||||||
|
*
|
||||||
|
* Delete the product from the cart (interface)
|
||||||
|
*
|
||||||
|
* @param {HTMLButtonElement|HTMLInputElement} element Handler elememnt of the product
|
||||||
|
* @param {HTMLElement} product The product element
|
||||||
|
* @param {number} amount Amount of deletings
|
||||||
|
* @param {bool} remove Remove the product element if json.amount === 0?
|
||||||
|
* @param {bool} force Ignore the damper? (false)
|
||||||
|
*
|
||||||
|
* @return {bool} Execution completed with an error?
|
||||||
|
*/
|
||||||
|
static delete(
|
||||||
|
element,
|
||||||
|
product,
|
||||||
|
amount = 1,
|
||||||
|
remove = false,
|
||||||
|
force = false,
|
||||||
|
) {
|
||||||
|
// Blocking the element
|
||||||
|
element.setAttribute("disabled", "true");
|
||||||
|
|
||||||
|
core.modules.connect("damper").then(
|
||||||
|
() => {
|
||||||
|
// Imported the damper module
|
||||||
|
|
||||||
|
// Execute under damper
|
||||||
|
this.product.damper(
|
||||||
|
element,
|
||||||
|
product,
|
||||||
|
"delete",
|
||||||
|
amount,
|
||||||
|
remove,
|
||||||
|
force,
|
||||||
|
);
|
||||||
|
},
|
||||||
|
() => {
|
||||||
|
// Not imported the damper module
|
||||||
|
|
||||||
|
// Execute
|
||||||
|
this.product.system(
|
||||||
|
element,
|
||||||
|
product,
|
||||||
|
"delete",
|
||||||
|
amount,
|
||||||
|
remove,
|
||||||
|
force,
|
||||||
|
);
|
||||||
|
},
|
||||||
|
);
|
||||||
|
|
||||||
|
// Exit (success)
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set
|
||||||
|
*
|
||||||
|
* Set amount of the product in the cart (interface)
|
||||||
|
*
|
||||||
|
* @param {HTMLButtonElement|HTMLInputElement} element Handler elememnt of the product
|
||||||
|
* @param {HTMLElement} product The product element
|
||||||
|
* @param {number} amount Amount of the product in the cart to be setted
|
||||||
|
* @param {bool} remove Remove the product element if json.amount === 0?
|
||||||
|
* @param {bool} force Ignore the damper? (false)
|
||||||
|
*
|
||||||
|
* @return {bool} Execution completed with an error?
|
||||||
|
*/
|
||||||
|
static set(
|
||||||
|
element,
|
||||||
|
product,
|
||||||
|
amount = 1,
|
||||||
|
remove = false,
|
||||||
|
force = false,
|
||||||
|
) {
|
||||||
|
// Blocking the element
|
||||||
|
element.setAttribute("disabled", "true");
|
||||||
|
|
||||||
|
core.modules.connect("damper").then(
|
||||||
|
() => {
|
||||||
|
// Imported the damper module
|
||||||
|
|
||||||
|
// Execute under damper
|
||||||
|
this.product.damper(
|
||||||
|
element,
|
||||||
|
product,
|
||||||
|
"set",
|
||||||
|
amount,
|
||||||
|
remove,
|
||||||
|
force,
|
||||||
|
);
|
||||||
|
},
|
||||||
|
() => {
|
||||||
|
// Not imported the damper module
|
||||||
|
|
||||||
|
// Execute
|
||||||
|
this.product.system(
|
||||||
|
element,
|
||||||
|
product,
|
||||||
|
"set",
|
||||||
|
amount,
|
||||||
|
remove,
|
||||||
|
force,
|
||||||
|
);
|
||||||
|
},
|
||||||
|
);
|
||||||
|
|
||||||
|
// Exit (success)
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The product
|
||||||
|
*
|
||||||
|
* Handle the product in the cart (system)
|
||||||
|
*
|
||||||
|
* @param {HTMLButtonElement|HTMLInputElement} element Handler element of the product
|
||||||
|
* @param {HTMLElement} product The product element
|
||||||
|
* @param {string} type Type of action with the product
|
||||||
|
* @param {number} amount Amount of product to handle
|
||||||
|
* @param {bool} remove Remove the product element if json.amount === 0?
|
||||||
|
*
|
||||||
|
* @return {bool} Execution completed with an error?
|
||||||
|
*/
|
||||||
|
static product(
|
||||||
|
element,
|
||||||
|
product,
|
||||||
|
type,
|
||||||
|
amount = null,
|
||||||
|
remove = false,
|
||||||
|
) {
|
||||||
|
core.modules.connect("damper").then(
|
||||||
|
() => {
|
||||||
|
// Imported the damper module
|
||||||
|
|
||||||
|
// Execute under damper
|
||||||
|
this.product.damper(
|
||||||
|
element,
|
||||||
|
product,
|
||||||
|
type,
|
||||||
|
amount,
|
||||||
|
remove,
|
||||||
|
force,
|
||||||
|
);
|
||||||
|
},
|
||||||
|
() => {
|
||||||
|
// Not imported the damper module
|
||||||
|
|
||||||
|
// Execute
|
||||||
|
this.product.system(
|
||||||
|
element,
|
||||||
|
product,
|
||||||
|
type,
|
||||||
|
amount,
|
||||||
|
remove,
|
||||||
|
force,
|
||||||
|
);
|
||||||
|
},
|
||||||
|
);
|
||||||
|
|
||||||
|
// Exit (success)
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @name Summary
|
||||||
|
*
|
||||||
|
* @description
|
||||||
|
* Initialize summary of products the cart (system)
|
||||||
|
*
|
||||||
|
* @return {Promise}
|
||||||
|
*/
|
||||||
|
static async summary() {
|
||||||
|
// Request
|
||||||
|
return await core.request("/cart/summary")
|
||||||
|
.then((json) => {
|
||||||
|
if (json) {
|
||||||
|
// Received a JSON-response
|
||||||
|
|
||||||
|
if (
|
||||||
|
json.errors !== null &&
|
||||||
|
typeof json.errors === "object" &&
|
||||||
|
json.errors.length > 0
|
||||||
|
) {
|
||||||
|
// Fail (received errors)
|
||||||
|
} else {
|
||||||
|
// Success (not received errors)
|
||||||
|
|
||||||
|
// Initializing the summary amount <span> element
|
||||||
|
const amount = document.getElementById("amount");
|
||||||
|
|
||||||
|
if (amount instanceof HTMLElement) {
|
||||||
|
// Initialized the summary amount element
|
||||||
|
|
||||||
|
// Writing summmary amount into the summary amount element
|
||||||
|
amount.innerText = json.amount;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Initializing the summary cost <span> element
|
||||||
|
const cost = document.getElementById("cost");
|
||||||
|
|
||||||
|
if (cost instanceof HTMLElement) {
|
||||||
|
// Initialized the summary cost element
|
||||||
|
|
||||||
|
// Writing summmary cost into the summary cost element
|
||||||
|
cost.innerText = json.cost;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
core.modules.connect("damper").then(() => {
|
||||||
|
// Imported the damper module
|
||||||
|
|
||||||
|
Object.assign(
|
||||||
|
cart.product,
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* Toggle
|
||||||
|
*
|
||||||
|
* Toggle the product in the cart (damper)
|
||||||
|
*
|
||||||
|
* @param {HTMLButtonElement|HTMLInputElement} element Handler elememnt of the product
|
||||||
|
* @param {HTMLElement} product The product element
|
||||||
|
* @param {bool} remove Remove the product element if json.amount === 0?
|
||||||
|
* @param {bool} force Ignore the damper? (false)
|
||||||
|
*
|
||||||
|
* @return {Promise}
|
||||||
|
*/
|
||||||
|
damper: core.damper(
|
||||||
|
(...variables) => cart.product.system(...variables).then(cart.summary),
|
||||||
|
300,
|
||||||
|
6,
|
||||||
|
),
|
||||||
|
},
|
||||||
|
);
|
||||||
|
});
|
||||||
|
|
||||||
|
Object.assign(
|
||||||
|
cart.product,
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* The product
|
||||||
|
*
|
||||||
|
* Handle the product in the cart (system)
|
||||||
|
*
|
||||||
|
* @param {HTMLButtonElement|HTMLInputElement} element Handler element of the product
|
||||||
|
* @param {HTMLElement} product The product element
|
||||||
|
* @param {string} type Type of action with the product
|
||||||
|
* @param {number} amount Amount of product to handle
|
||||||
|
* @param {bool} remove Remove the product element if json.amount === 0?
|
||||||
|
*
|
||||||
|
* @return {Promise|null}
|
||||||
|
*/
|
||||||
|
async system(
|
||||||
|
element,
|
||||||
|
product,
|
||||||
|
type,
|
||||||
|
amount = null,
|
||||||
|
remove = false,
|
||||||
|
resolve = () => {},
|
||||||
|
reject = () => {},
|
||||||
|
) {
|
||||||
|
try {
|
||||||
|
if (
|
||||||
|
(element instanceof HTMLButtonElement ||
|
||||||
|
element instanceof HTMLInputElement) &&
|
||||||
|
product instanceof HTMLElement
|
||||||
|
) {
|
||||||
|
// Validated
|
||||||
|
|
||||||
|
// Initializing the buffer of request body
|
||||||
|
let request = "";
|
||||||
|
|
||||||
|
// Initializing of identifier of the product
|
||||||
|
const identifier = +product.getAttribute(
|
||||||
|
"data-product-identifier",
|
||||||
|
);
|
||||||
|
|
||||||
|
if (typeof identifier === "number") {
|
||||||
|
// Validated identifier
|
||||||
|
|
||||||
|
// Writing to the buffer of request body
|
||||||
|
request += "&identifier=" + identifier;
|
||||||
|
|
||||||
|
if (
|
||||||
|
type === "toggle" ||
|
||||||
|
type === "write" ||
|
||||||
|
type === "delete" ||
|
||||||
|
type === "set"
|
||||||
|
) {
|
||||||
|
// Validated type
|
||||||
|
|
||||||
|
// Writing to the buffer of request body
|
||||||
|
request += "&type=" + type;
|
||||||
|
|
||||||
|
console.log(type, amount);
|
||||||
|
if (
|
||||||
|
(type === "toggle" &&
|
||||||
|
amount === null ||
|
||||||
|
typeof amount === "undefined") ||
|
||||||
|
(type === "set" &&
|
||||||
|
amount === 0 ||
|
||||||
|
amount === 100) ||
|
||||||
|
typeof amount === "number" &&
|
||||||
|
amount > 0 &&
|
||||||
|
amount < 100
|
||||||
|
) {
|
||||||
|
// Validated amount
|
||||||
|
|
||||||
|
console.log(amount);
|
||||||
|
if (type !== "toggle") {
|
||||||
|
// Not a toggle request
|
||||||
|
|
||||||
|
// Writing to the buffer of request body
|
||||||
|
request += "&amount=" + amount;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Request
|
||||||
|
return await core.request(
|
||||||
|
"/cart/product",
|
||||||
|
request,
|
||||||
|
)
|
||||||
|
.then(
|
||||||
|
(json) => {
|
||||||
|
if (json) {
|
||||||
|
// Received a JSON-response
|
||||||
|
|
||||||
|
if (
|
||||||
|
json.errors !== null &&
|
||||||
|
typeof json.errors === "object" &&
|
||||||
|
json.errors.length > 0
|
||||||
|
) {
|
||||||
|
// Fail (received errors)
|
||||||
|
} else {
|
||||||
|
// Success (not received errors)
|
||||||
|
|
||||||
|
if (remove && json.amount === 0) {
|
||||||
|
// Requested deleting of the product element when there is no the product in the cart
|
||||||
|
|
||||||
|
// Deleting the product element
|
||||||
|
product.remove();
|
||||||
|
} else {
|
||||||
|
// Not requested deleting the product element when there is no the product in the cart
|
||||||
|
|
||||||
|
// Unblocking the element
|
||||||
|
element.removeAttribute("disabled");
|
||||||
|
|
||||||
|
// Writing offset of hue-rotate to indicate that the product is in the cart
|
||||||
|
product.style.setProperty(
|
||||||
|
"--hue-rotate-offset",
|
||||||
|
json.amount + "0deg",
|
||||||
|
);
|
||||||
|
|
||||||
|
// Writing attribute with amount of the product in the cart
|
||||||
|
product.setAttribute(
|
||||||
|
"data-product-amount",
|
||||||
|
json.amount,
|
||||||
|
);
|
||||||
|
|
||||||
|
// Initializing the amount <span> element
|
||||||
|
const amounts = product.querySelectorAll(
|
||||||
|
'[data-product-parameter="amount"]',
|
||||||
|
);
|
||||||
|
|
||||||
|
for (const amount of amounts) {
|
||||||
|
// Iterating over an amount elements
|
||||||
|
|
||||||
|
if (amount instanceof HTMLInputElement) {
|
||||||
|
// The <input> element
|
||||||
|
|
||||||
|
// Writing amount of the product in the cart
|
||||||
|
amount.value = json.amount;
|
||||||
|
} else {
|
||||||
|
// Not the <input> element
|
||||||
|
|
||||||
|
// Writing amount of the product in the cart
|
||||||
|
amount.innerText = json.amount;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Exit (success)
|
||||||
|
resolve();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
() => reject(),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} catch (e) {
|
||||||
|
// Exit (fail)
|
||||||
|
reject(e);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
},
|
||||||
|
);
|
||||||
|
|
||||||
|
// Connecting to the core
|
||||||
|
if (!core.cart) core.cart = cart;
|
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,305 @@
|
||||||
|
"use strict";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @name Connection
|
||||||
|
*
|
||||||
|
* @description
|
||||||
|
* Implements actions with websocket connection
|
||||||
|
*
|
||||||
|
* @license http://www.wtfpl.net/ Do What The Fuck You Want To Public License
|
||||||
|
* @author Arsen Mirzaev Tatyano-Muradovich <arsen@mirzaev.sexy>
|
||||||
|
*/
|
||||||
|
export default class connection {
|
||||||
|
/**
|
||||||
|
* @name Type of the program
|
||||||
|
*/
|
||||||
|
static type = "module";
|
||||||
|
|
||||||
|
// Wrap of indicator of the connection
|
||||||
|
static wrap = document.getElementById("connection");
|
||||||
|
|
||||||
|
// Indicator of the connection
|
||||||
|
static indicator = this.wrap?.getElementsByTagName("i")[0];
|
||||||
|
|
||||||
|
// Description of the connection
|
||||||
|
static description = this.wrap?.getElementsByTagName("small")[0];
|
||||||
|
|
||||||
|
// Statuc of the connection
|
||||||
|
static connected = false;
|
||||||
|
|
||||||
|
// Duration of the disconnected status
|
||||||
|
static timeout = 0;
|
||||||
|
|
||||||
|
// Instance of the time counter in disconnected status
|
||||||
|
static counter;
|
||||||
|
|
||||||
|
// Socket address (xn--e1ajlli это сокет)
|
||||||
|
static socket = "wss://arming.dev.mirzaev.sexy:9502";
|
||||||
|
|
||||||
|
// Instance of connection to the socket
|
||||||
|
static session;
|
||||||
|
|
||||||
|
// Iterval for reconnect
|
||||||
|
static interval;
|
||||||
|
|
||||||
|
// Attempts to connect (when connection.readyState === 0)
|
||||||
|
static attempts = 0;
|
||||||
|
|
||||||
|
// Interval for block
|
||||||
|
static block;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Initialize status of the connection to socket
|
||||||
|
*
|
||||||
|
* @param {bool} connected Connected?
|
||||||
|
*
|
||||||
|
* @return {void}
|
||||||
|
*/
|
||||||
|
static status(connected = false) {
|
||||||
|
if (this.indicator instanceof HTMLElement) {
|
||||||
|
// Initialized the indicator
|
||||||
|
|
||||||
|
this.connected = connected;
|
||||||
|
|
||||||
|
if (this.connected) {
|
||||||
|
// Connected
|
||||||
|
|
||||||
|
this.wrap.setAttribute("title", "Connected");
|
||||||
|
|
||||||
|
this.indicator.classList.remove("disconnected");
|
||||||
|
this.indicator.classList.add("connected");
|
||||||
|
|
||||||
|
clearInterval(this.counter);
|
||||||
|
this.description.innerText = "";
|
||||||
|
this.counter = undefined;
|
||||||
|
this.timeout = 0;
|
||||||
|
} else {
|
||||||
|
// Disconnected
|
||||||
|
|
||||||
|
this.wrap.setAttribute("title", "Disconnected");
|
||||||
|
|
||||||
|
this.indicator.classList.remove("connected");
|
||||||
|
this.indicator.classList.add("disconnected");
|
||||||
|
|
||||||
|
if (typeof this.counter === "undefined") {
|
||||||
|
this.counter = setInterval(() => {
|
||||||
|
this.timeout += 0.01;
|
||||||
|
this.description.innerText = this.timeout.toFixed(2);
|
||||||
|
}, 10);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Connect to the socket
|
||||||
|
*
|
||||||
|
* @param {bool|number} interval Connection check interval (ms)
|
||||||
|
* @param {function} preprocessing Will be executed every cycle
|
||||||
|
* @param {function} onmessage New message
|
||||||
|
* @param {function} onopen Connection opened
|
||||||
|
* @param {function} onclose Connection closed
|
||||||
|
* @param {function} onerror An error has occurred
|
||||||
|
*
|
||||||
|
* @return {Promise}
|
||||||
|
*/
|
||||||
|
static connect(
|
||||||
|
interval = false,
|
||||||
|
preprocessing,
|
||||||
|
onmessage,
|
||||||
|
onopen,
|
||||||
|
onclose,
|
||||||
|
onerror,
|
||||||
|
) {
|
||||||
|
return new Promise((resolve, reject) => {
|
||||||
|
try {
|
||||||
|
if (typeof interval === "number" && interval > 0) {
|
||||||
|
// Connect with automatic reconnect
|
||||||
|
|
||||||
|
if (typeof this.interval === "undefined") {
|
||||||
|
this.interval = setInterval(() => {
|
||||||
|
preprocessing();
|
||||||
|
|
||||||
|
if (
|
||||||
|
!(this.session instanceof WebSocket) ||
|
||||||
|
(this.session.readyState === 3 ||
|
||||||
|
this.session.readyState === 4) ||
|
||||||
|
(this.session.readyState === 0 &&
|
||||||
|
++this.attempts > 10)
|
||||||
|
) {
|
||||||
|
this.attempts = 0;
|
||||||
|
|
||||||
|
if (this.session instanceof WebSocket) {
|
||||||
|
this.session.close();
|
||||||
|
}
|
||||||
|
|
||||||
|
this.session = new WebSocket(this.socket);
|
||||||
|
this.session.addEventListener("message", (e) => {
|
||||||
|
try {
|
||||||
|
const json = JSON.parse(e.data);
|
||||||
|
|
||||||
|
if (json.type === "registration") {
|
||||||
|
// Подключение сокета к сессии
|
||||||
|
|
||||||
|
fetch("/socket/registration", {
|
||||||
|
method: "POST",
|
||||||
|
headers: {
|
||||||
|
"Content-Type": "application/x-www-form-urlencoded",
|
||||||
|
},
|
||||||
|
body: `key=${json.key}`,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
} catch (_e) {}
|
||||||
|
});
|
||||||
|
this.session.addEventListener("message", onmessage);
|
||||||
|
this.session.addEventListener("open", onopen);
|
||||||
|
this.session.addEventListener("close", onclose);
|
||||||
|
this.session.addEventListener("error", onerror);
|
||||||
|
|
||||||
|
resolve(this.session);
|
||||||
|
} else resolve(this.session);
|
||||||
|
}, interval);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// Connect without reconnecting
|
||||||
|
|
||||||
|
if (
|
||||||
|
!(this.session instanceof WebSocket) ||
|
||||||
|
(this.session.readyState === 3 ||
|
||||||
|
this.session.readyState === 4)
|
||||||
|
) {
|
||||||
|
if (this.session instanceof WebSocket) {
|
||||||
|
this.session.close();
|
||||||
|
}
|
||||||
|
|
||||||
|
this.session = new WebSocket(this.socket);
|
||||||
|
this.session.addEventListener("message", onmessage);
|
||||||
|
this.session.addEventListener("open", onopen);
|
||||||
|
this.session.addEventListener("close", onclose);
|
||||||
|
this.session.addEventListener("error", onerror);
|
||||||
|
|
||||||
|
resolve(this.session);
|
||||||
|
} else resolve(this.session);
|
||||||
|
}
|
||||||
|
} catch (_e) {}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Core is connected to the socket?
|
||||||
|
*
|
||||||
|
* @return {bool}
|
||||||
|
*/
|
||||||
|
static connected() {
|
||||||
|
return this.session instanceof WebSocket &&
|
||||||
|
this.session.readyState === 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
connection.connect(
|
||||||
|
3000,
|
||||||
|
() =>
|
||||||
|
connection.status(
|
||||||
|
connection.session instanceof WebSocket &&
|
||||||
|
connection.session.readyState === 1,
|
||||||
|
),
|
||||||
|
(e) => {
|
||||||
|
try {
|
||||||
|
const json = JSON.parse(e.data);
|
||||||
|
|
||||||
|
if (json.target === "task") {
|
||||||
|
// Заявка
|
||||||
|
|
||||||
|
// Инициализация строки
|
||||||
|
const row = document.getElementById(json._key);
|
||||||
|
|
||||||
|
if (row instanceof HTMLElement) {
|
||||||
|
// Инициализирована строка
|
||||||
|
|
||||||
|
if (json.type === "blocked") {
|
||||||
|
// Заблокирована заявка
|
||||||
|
|
||||||
|
// Запись статуса: "заблокирована"
|
||||||
|
row.setAttribute("data-blocked", json.account._key);
|
||||||
|
row.setAttribute(
|
||||||
|
"title",
|
||||||
|
"Редактирует: " + json.account.name,
|
||||||
|
);
|
||||||
|
|
||||||
|
// Удалить блокировку (60000 === 1 минута) (в базе данных стоит expires 1 минута тоже)
|
||||||
|
setTimeout(() => {
|
||||||
|
// Удаление статуса: "заблокирована"
|
||||||
|
row.removeAttribute("data-blocked");
|
||||||
|
row.removeAttribute("title");
|
||||||
|
|
||||||
|
// Обновление строки
|
||||||
|
tasks.row(row);
|
||||||
|
}, 60000);
|
||||||
|
} else if (json.type === "unblocked") {
|
||||||
|
// Разблокирована заявка
|
||||||
|
|
||||||
|
// Удаление статуса: "заблокирована"
|
||||||
|
row.removeAttribute("data-blocked");
|
||||||
|
row.removeAttribute("title");
|
||||||
|
|
||||||
|
// Обновление строки
|
||||||
|
tasks.row(row);
|
||||||
|
} else if (json.type === "updated") {
|
||||||
|
// Обновлена заявка
|
||||||
|
|
||||||
|
// Обновление строки
|
||||||
|
tasks.row(row);
|
||||||
|
} else if (json.type === "deleted") {
|
||||||
|
// Удалена заявка
|
||||||
|
|
||||||
|
// Удаление строки
|
||||||
|
row.remove();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} catch (_e) {}
|
||||||
|
// Инициализация идентифиатора
|
||||||
|
//const id = row.getAttribute("id");
|
||||||
|
|
||||||
|
// Инициализация количества непрочитанных сообщений
|
||||||
|
//const messages = row.lastElementChild.innerText;
|
||||||
|
|
||||||
|
// Инициализация статуса активной строки
|
||||||
|
//const selected = row.getAttribute("data-selected");
|
||||||
|
|
||||||
|
// Реинициализация строки
|
||||||
|
//row.outerHTML = data.rows;
|
||||||
|
|
||||||
|
// Реинициализация перезаписанной строки
|
||||||
|
//row = document.getElementById(id);
|
||||||
|
|
||||||
|
// Копирование статуса активной строки
|
||||||
|
//if (
|
||||||
|
// typeof selected === "string" &&
|
||||||
|
// selected === "true" &&
|
||||||
|
// document.body.contains(document.getElementById("popup"))
|
||||||
|
//) {
|
||||||
|
// row.setAttribute("data-selected", "true");
|
||||||
|
//}
|
||||||
|
},
|
||||||
|
(e) => {
|
||||||
|
//connection.status(
|
||||||
|
// connection instanceof WebSocket &&
|
||||||
|
// connection.readyState === 1,
|
||||||
|
//)
|
||||||
|
//console.log("Connected to WebSocket!");
|
||||||
|
},
|
||||||
|
(e) => {
|
||||||
|
//connection.status(
|
||||||
|
// connection instanceof WebSocket &&
|
||||||
|
// connection.readyState === 1,
|
||||||
|
//)
|
||||||
|
//console.log("Connection closed");
|
||||||
|
},
|
||||||
|
(e) => {
|
||||||
|
//console.log("Error happens");
|
||||||
|
},
|
||||||
|
);
|
||||||
|
|
||||||
|
// Connecting to the core
|
||||||
|
if (!core.connection) core.connection = connection;
|
|
@ -0,0 +1,76 @@
|
||||||
|
"use strict";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @name Damper
|
||||||
|
*
|
||||||
|
* @description
|
||||||
|
* Execute multiple "function" calls in a "timeout" amount of time just once
|
||||||
|
*
|
||||||
|
* @param {function} function Function to execute after damping
|
||||||
|
* @param {number} timeout Timer in milliseconds (ms)
|
||||||
|
* @param {number} force Argument number storing the status of enforcement execution (see @example)
|
||||||
|
*
|
||||||
|
* @return {Promise}
|
||||||
|
*
|
||||||
|
* @example
|
||||||
|
* a = damper(
|
||||||
|
* async (
|
||||||
|
* a, // 0
|
||||||
|
* b, // 1
|
||||||
|
* c, // 2
|
||||||
|
* force = false, // 3
|
||||||
|
* d, // 4
|
||||||
|
* resolve,
|
||||||
|
* reject
|
||||||
|
* ) => {
|
||||||
|
* // Body of the function
|
||||||
|
*
|
||||||
|
* resolve();
|
||||||
|
* },
|
||||||
|
* 500,
|
||||||
|
* 3, // 3 -> "force" argument
|
||||||
|
* );
|
||||||
|
*
|
||||||
|
* a('for a', 'for b', 'for c', true, 'for d'); // Force execute is enabled
|
||||||
|
*
|
||||||
|
* @license http://www.wtfpl.net/ Do What The Fuck You Want To Public License
|
||||||
|
* @author Arsen Mirzaev Tatyano-Muradovich <arsen@mirzaev.sexy>
|
||||||
|
*/
|
||||||
|
export default function damper(func, timeout = 300, force) {
|
||||||
|
// Declaring of the timer for executing the function
|
||||||
|
let timer;
|
||||||
|
|
||||||
|
return ((...args) => {
|
||||||
|
return new Promise((resolve, reject) => {
|
||||||
|
// Deinitializing of the timer
|
||||||
|
clearTimeout(timer);
|
||||||
|
|
||||||
|
if (typeof force === "number" && args[force]) {
|
||||||
|
// Requested execution with ignoring the timer
|
||||||
|
|
||||||
|
// Deleting the force argument
|
||||||
|
if (typeof force === "number") delete args[force - 1];
|
||||||
|
|
||||||
|
// Writing promise handlers into the arguments variable
|
||||||
|
args.push(resolve, reject);
|
||||||
|
|
||||||
|
// Executing the function
|
||||||
|
func.apply(this, args);
|
||||||
|
} else {
|
||||||
|
// Normal execution
|
||||||
|
|
||||||
|
// Deleting the force argument
|
||||||
|
if (typeof force === "number") delete args[force - 1];
|
||||||
|
|
||||||
|
// Writing promise handlers into the arguments variable
|
||||||
|
args.push(resolve, reject);
|
||||||
|
|
||||||
|
// Resetting the timer and executing the function when the timer expires
|
||||||
|
timer = setTimeout(() => func.apply(this, args), timeout);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
// Connecting to the core
|
||||||
|
if (!core.damper) core.damper = damper;
|
|
@ -0,0 +1,161 @@
|
||||||
|
"use strict";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @name Delivery
|
||||||
|
*
|
||||||
|
* @description
|
||||||
|
* Implements actions with delivery
|
||||||
|
*
|
||||||
|
* @license http://www.wtfpl.net/ Do What The Fuck You Want To Public License
|
||||||
|
* @author Arsen Mirzaev Tatyano-Muradovich <arsen@mirzaev.sexy>
|
||||||
|
*/
|
||||||
|
export default class delivery {
|
||||||
|
/**
|
||||||
|
* @name Type of the program
|
||||||
|
*/
|
||||||
|
static type = "module";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @name Company
|
||||||
|
*
|
||||||
|
* @description
|
||||||
|
* Choose a delivery company (interface)
|
||||||
|
*
|
||||||
|
* @param {HTNLElement} element Handler element
|
||||||
|
* @param {string} identifier Identifier of the delivery company
|
||||||
|
* @param {bool} force Ignore the damper? (false)
|
||||||
|
*
|
||||||
|
* @return {bool} Execution completed with an error?
|
||||||
|
*/
|
||||||
|
static company = (element, identifier, force = false) => {
|
||||||
|
core.modules.connect("damper").then(
|
||||||
|
() => {
|
||||||
|
// Imported the damper module
|
||||||
|
|
||||||
|
// Execute under damper
|
||||||
|
this.company.damper(element, identifier, force);
|
||||||
|
},
|
||||||
|
() => {
|
||||||
|
// Not imported the damper module
|
||||||
|
|
||||||
|
// Execute
|
||||||
|
this.company.system(element, identifier, force);
|
||||||
|
},
|
||||||
|
);
|
||||||
|
|
||||||
|
// Exit (success)
|
||||||
|
return false;
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @name City
|
||||||
|
*
|
||||||
|
* @description
|
||||||
|
* Write name of a city for delivery (interface)
|
||||||
|
*
|
||||||
|
* @param {HTNLInputElement} element Handler element <input>
|
||||||
|
* @param {bool} force Ignore the damper? (false)
|
||||||
|
*
|
||||||
|
* @return {bool} Execution completed with an error?
|
||||||
|
*/
|
||||||
|
static company = (element, force = false) => {
|
||||||
|
core.modules.connect("damper").then(
|
||||||
|
() => {
|
||||||
|
// Imported the damper module
|
||||||
|
|
||||||
|
// Execute under damper
|
||||||
|
this.city.damper(element, identifier, force);
|
||||||
|
},
|
||||||
|
() => {
|
||||||
|
// Not imported the damper module
|
||||||
|
|
||||||
|
// Execute
|
||||||
|
this.company.system(element, identifier, force);
|
||||||
|
},
|
||||||
|
);
|
||||||
|
|
||||||
|
// Exit (success)
|
||||||
|
return false;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
core.modules.connect("damper").then(() => {
|
||||||
|
// Imported the damper module
|
||||||
|
|
||||||
|
Object.assign(
|
||||||
|
delivery.company,
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* @name Write
|
||||||
|
*
|
||||||
|
* @description
|
||||||
|
* Choose a delivery company (damper)
|
||||||
|
*
|
||||||
|
* @param {HTNLElement} element Handler element
|
||||||
|
* @param {string} identifier Identifier of the delivery company
|
||||||
|
* @param {bool} force Ignore the damper? (false)
|
||||||
|
*
|
||||||
|
* @return {Promise}
|
||||||
|
*/
|
||||||
|
damper: core.damper(
|
||||||
|
(...variables) => delivery.company.system(...variables),
|
||||||
|
300,
|
||||||
|
3,
|
||||||
|
),
|
||||||
|
},
|
||||||
|
);
|
||||||
|
});
|
||||||
|
|
||||||
|
Object.assign(
|
||||||
|
delivery.company,
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* @name Write
|
||||||
|
*
|
||||||
|
* @description
|
||||||
|
* Choose a delivery company (system)
|
||||||
|
*
|
||||||
|
* @param {string} identifier Identifier of the delivery company
|
||||||
|
*
|
||||||
|
* @return {Promise}
|
||||||
|
*/
|
||||||
|
async system(
|
||||||
|
type,
|
||||||
|
value,
|
||||||
|
resolve = () => {},
|
||||||
|
reject = () => {},
|
||||||
|
) {
|
||||||
|
try {
|
||||||
|
if (
|
||||||
|
typeof type === "string" &&
|
||||||
|
(typeof value === "string" || typeof valye === "number")
|
||||||
|
) {
|
||||||
|
// Received and validated required arguments
|
||||||
|
|
||||||
|
// Sending request to the server
|
||||||
|
return await core.buffer.write(`delivery_${type}`, value)
|
||||||
|
.then(
|
||||||
|
(json) => {
|
||||||
|
try {
|
||||||
|
|
||||||
|
|
||||||
|
// Exit (success)
|
||||||
|
resolve(json);
|
||||||
|
} catch (e) {
|
||||||
|
// Exit (fail)
|
||||||
|
reject(e);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
() => reject(),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
} catch (e) {
|
||||||
|
// Exit (fail)
|
||||||
|
reject(e);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
},
|
||||||
|
);
|
||||||
|
|
||||||
|
// Connecting to the core
|
||||||
|
if (!core.delivery) core.delivery = delivery;
|
|
@ -0,0 +1,250 @@
|
||||||
|
"use strict";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @name Loader
|
||||||
|
*
|
||||||
|
* @description
|
||||||
|
* Implements actions with loading and rendering content
|
||||||
|
*
|
||||||
|
* @license http://www.wtfpl.net/ Do What The Fuck You Want To Public License
|
||||||
|
* @author Arsen Mirzaev Tatyano-Muradovich <arsen@mirzaev.sexy>
|
||||||
|
*/
|
||||||
|
export default class loader {
|
||||||
|
/**
|
||||||
|
* @name Type of the program
|
||||||
|
*/
|
||||||
|
static type = "module";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @name Load
|
||||||
|
*
|
||||||
|
* @param {string} uri
|
||||||
|
* @param {string} body
|
||||||
|
*
|
||||||
|
* @return {Promise}
|
||||||
|
*/
|
||||||
|
static async load(uri = "/", body) {
|
||||||
|
if (typeof uri === "string") {
|
||||||
|
// Received and validated uri
|
||||||
|
|
||||||
|
return await core
|
||||||
|
.request(
|
||||||
|
uri,
|
||||||
|
body,
|
||||||
|
"POST",
|
||||||
|
{
|
||||||
|
"Content-Type": "application/x-www-form-urlencoded",
|
||||||
|
Accept: "application/json",
|
||||||
|
},
|
||||||
|
"json",
|
||||||
|
)
|
||||||
|
.then((json) => {
|
||||||
|
if (json) {
|
||||||
|
// Received a JSON-response
|
||||||
|
|
||||||
|
if (
|
||||||
|
json.errors !== null &&
|
||||||
|
typeof json.errors === "object" &&
|
||||||
|
json.errors.length > 0
|
||||||
|
) {
|
||||||
|
// Fail (received errors)
|
||||||
|
} else {
|
||||||
|
// Success (not received errors)
|
||||||
|
|
||||||
|
// Writing to the browser history
|
||||||
|
history.pushState({}, json.title ?? uri, uri);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The <title>
|
||||||
|
*
|
||||||
|
* The title of the page
|
||||||
|
*/
|
||||||
|
if (
|
||||||
|
typeof json.title === "string" &&
|
||||||
|
json.title.length > 0
|
||||||
|
) {
|
||||||
|
// Received text for the <title> of the page
|
||||||
|
|
||||||
|
// Search for the <title> element (document.title)
|
||||||
|
const title = document.getElementsByTagName("title")[0];
|
||||||
|
|
||||||
|
if (title instanceof HTMLElement) {
|
||||||
|
// Found the <title> element
|
||||||
|
|
||||||
|
// Writing into the <title> element
|
||||||
|
title.innerText = json.title;
|
||||||
|
} else {
|
||||||
|
// Not found the <title> element
|
||||||
|
|
||||||
|
// Initialize the <title> element
|
||||||
|
const title = document.createElement("title");
|
||||||
|
|
||||||
|
// Inititalize the <head> element (document.head)
|
||||||
|
const head = document.getElementsByTagName("head")[0];
|
||||||
|
|
||||||
|
if (head instanceof HTMLElement) {
|
||||||
|
// Found the <head> element
|
||||||
|
|
||||||
|
// Writing the <title> element into the <head> element
|
||||||
|
head.appendChild(title);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Writing title into the <title> element
|
||||||
|
title.innerText = json.title;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The <header> element
|
||||||
|
*/
|
||||||
|
if (
|
||||||
|
typeof json.header === "string" &&
|
||||||
|
json.header.length > 0
|
||||||
|
) {
|
||||||
|
// Received and validated the header HTML-code
|
||||||
|
|
||||||
|
if (core.header instanceof HTMLElement) {
|
||||||
|
// Found the <header> element
|
||||||
|
|
||||||
|
// Writing into the <header> element
|
||||||
|
core.header.outerHTML = json.header;
|
||||||
|
|
||||||
|
// Reinitializing the parameter with the <header> element
|
||||||
|
core.header = document.getElementsByTagName("header")[0];
|
||||||
|
} else {
|
||||||
|
// Not found the <header> element
|
||||||
|
|
||||||
|
// Initialize the <header> element
|
||||||
|
core.header = document.createElement("header");
|
||||||
|
|
||||||
|
// Inititalize the <body> element (document.body)
|
||||||
|
const body = document.getElementsByTagName("body")[0];
|
||||||
|
|
||||||
|
if (body instanceof HTMLElement) {
|
||||||
|
// Found the <body> element
|
||||||
|
|
||||||
|
if (core.main instanceof HTMLElement) {
|
||||||
|
// Found the <main> element
|
||||||
|
|
||||||
|
// Writing the <header> element before the <main> element
|
||||||
|
body.insertBefore(core.header, core.main);
|
||||||
|
} else if (core.footer instanceof HTMLElement) {
|
||||||
|
// Fount the <footer> element
|
||||||
|
|
||||||
|
// Writing the <header> element before the <footer> element
|
||||||
|
body.insertBefore(core.header, core.footer);
|
||||||
|
} else {
|
||||||
|
// Not found the <main> element and the <footer> element
|
||||||
|
|
||||||
|
// Search for the last <section> element inside the <body> element
|
||||||
|
const section = document.body.querySelector(
|
||||||
|
"body > section:last-of-type",
|
||||||
|
);
|
||||||
|
|
||||||
|
if (section instanceof HTMLElement) {
|
||||||
|
// Found the last <section> element inside the <body> element
|
||||||
|
|
||||||
|
// Writing the <header> element after the last <section> element inside the <body> element
|
||||||
|
body.insertBefore(
|
||||||
|
core.header,
|
||||||
|
section.nextSibling,
|
||||||
|
);
|
||||||
|
} else {
|
||||||
|
// Not found section elements <section> inside the <body> element
|
||||||
|
|
||||||
|
// Writing the <header> element into the <body> element
|
||||||
|
body.appendChild(core.header);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Writing into the <header> element
|
||||||
|
core.header.outerHTML = json.header;
|
||||||
|
|
||||||
|
// Reinitializing the parameter with the <header> element
|
||||||
|
core.header = document.getElementsByTagName("header")[0];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The <main> element
|
||||||
|
*
|
||||||
|
* The main content of the page
|
||||||
|
*/
|
||||||
|
if (typeof json.main === "string" && json.main.length > 0) {
|
||||||
|
// Received and validated the <main> HTML-code
|
||||||
|
|
||||||
|
if (core.main instanceof HTMLElement) {
|
||||||
|
// Found the <main> element
|
||||||
|
|
||||||
|
// Writing into the <main> element
|
||||||
|
core.main.outerHTML = json.main;
|
||||||
|
|
||||||
|
// Reinitializing the parameter with the <main> element
|
||||||
|
core.main = document.getElementsByTagName("main")[0];
|
||||||
|
} else {
|
||||||
|
// Not found the <main> element
|
||||||
|
|
||||||
|
// Initialize the <main> element
|
||||||
|
core.main = document.createElement("main");
|
||||||
|
|
||||||
|
// Inititalize the <body> element (document.body)
|
||||||
|
const body = document.getElementsByTagName("body")[0];
|
||||||
|
|
||||||
|
if (body instanceof HTMLElement) {
|
||||||
|
// Found the <body> element
|
||||||
|
|
||||||
|
if (core.header instanceof HTMLElement) {
|
||||||
|
// Found the <header> element
|
||||||
|
|
||||||
|
// Writing the <main> element after the <header> element
|
||||||
|
body.insertBefore(
|
||||||
|
core.main,
|
||||||
|
core.header.nextSibling,
|
||||||
|
);
|
||||||
|
} else if (core.footer instanceof HTMLElement) {
|
||||||
|
// Fount the <footer> element
|
||||||
|
|
||||||
|
// Writing the <main> element before the <footer> element
|
||||||
|
body.insertBefore(core.main, core.footer);
|
||||||
|
} else {
|
||||||
|
// Not found the <header> element and the <footer> element
|
||||||
|
|
||||||
|
// Search for the last <section> element inside the <body> element
|
||||||
|
const section = document.body.querySelector(
|
||||||
|
"body > section:last-of-type",
|
||||||
|
);
|
||||||
|
|
||||||
|
if (section instanceof HTMLElement) {
|
||||||
|
// Found the last <section> element inside the <body> element
|
||||||
|
|
||||||
|
// Writing the <main> element after the last <section> element inside the <body> element
|
||||||
|
body.insertBefore(core.main, section.nextSibling);
|
||||||
|
} else {
|
||||||
|
// Not found section elements <section> inside the <body> element
|
||||||
|
|
||||||
|
// Writing the <main> element into the <body> element
|
||||||
|
body.appendChild(core.main);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Writing into the <main> element
|
||||||
|
core.main.outerHTML = json.main;
|
||||||
|
|
||||||
|
// Reinitializing the parameter with the <main> element
|
||||||
|
core.main = document.getElementsByTagName("main")[0];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Exit (success)
|
||||||
|
return json;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Connecting to the core
|
||||||
|
if (!core.loader) core.loader = loader;
|
|
@ -0,0 +1,129 @@
|
||||||
|
"use strict";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @name Session
|
||||||
|
*
|
||||||
|
* @description
|
||||||
|
* Implements actions with sessions
|
||||||
|
*
|
||||||
|
* @license http://www.wtfpl.net/ Do What The Fuck You Want To Public License
|
||||||
|
* @author Arsen Mirzaev Tatyano-Muradovich <arsen@mirzaev.sexy>
|
||||||
|
*/
|
||||||
|
export default class session {
|
||||||
|
/**
|
||||||
|
* @name Type of the program
|
||||||
|
*/
|
||||||
|
static type = "module";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @name Buffer
|
||||||
|
*/
|
||||||
|
static buffer = class buffer {
|
||||||
|
/**
|
||||||
|
* @name Write
|
||||||
|
*
|
||||||
|
* @description
|
||||||
|
* Write to the session buffer (interface)
|
||||||
|
*
|
||||||
|
* @param {string} name Name of the parameter
|
||||||
|
* @param {string} value Value of the parameter (it can be JSON)
|
||||||
|
* @param {bool} force Ignore the damper? (false)
|
||||||
|
*
|
||||||
|
* @return {bool} Execution completed with an error?
|
||||||
|
*/
|
||||||
|
static write = (name, value, force = false) => {
|
||||||
|
core.modules.connect("damper").then(
|
||||||
|
() => {
|
||||||
|
// Imported the damper module
|
||||||
|
|
||||||
|
// Execute under damper
|
||||||
|
this.write.damper(name, value, force);
|
||||||
|
},
|
||||||
|
() => {
|
||||||
|
// Not imported the damper module
|
||||||
|
|
||||||
|
// Execute
|
||||||
|
this.write.system(name, value, force);
|
||||||
|
},
|
||||||
|
);
|
||||||
|
|
||||||
|
// Exit (success)
|
||||||
|
return false;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
core.modules.connect("damper").then(() => {
|
||||||
|
// Imported the damper module
|
||||||
|
|
||||||
|
Object.assign(
|
||||||
|
session.buffer.write,
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* @name Write
|
||||||
|
*
|
||||||
|
* @description
|
||||||
|
* Write to the session buffer (damper)
|
||||||
|
*
|
||||||
|
* @param {string} name Name of the parameter
|
||||||
|
* @param {string} value Value of the parameter (it can be JSON)
|
||||||
|
* @param {bool} force Ignore the damper? (false)
|
||||||
|
*
|
||||||
|
* @return {Promise}
|
||||||
|
*/
|
||||||
|
damper: core.damper(
|
||||||
|
(...variables) => session.buffer.write.system(...variables),
|
||||||
|
300,
|
||||||
|
3,
|
||||||
|
),
|
||||||
|
},
|
||||||
|
);
|
||||||
|
});
|
||||||
|
|
||||||
|
Object.assign(
|
||||||
|
session.buffer.write,
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* @name Write
|
||||||
|
*
|
||||||
|
* @description
|
||||||
|
* Write to the session buffer (system)
|
||||||
|
*
|
||||||
|
* @param {string} name Name of the parameter
|
||||||
|
* @param {string} value Value of the parameter (it can be JSON)
|
||||||
|
*
|
||||||
|
* @return {Promise}
|
||||||
|
*/
|
||||||
|
async system(
|
||||||
|
name,
|
||||||
|
value,
|
||||||
|
resolve = () => {},
|
||||||
|
reject = () => {},
|
||||||
|
) {
|
||||||
|
if (typeof name === "string" && typeof value === "string") {
|
||||||
|
// Received and validated required arguments
|
||||||
|
|
||||||
|
// Sending request to the server
|
||||||
|
return await core.request(
|
||||||
|
"/session/write",
|
||||||
|
`${name}=${value}`,
|
||||||
|
"POST",
|
||||||
|
)
|
||||||
|
.then(
|
||||||
|
(json) => {
|
||||||
|
if (json) {
|
||||||
|
// Received a JSON-response
|
||||||
|
|
||||||
|
// Exit (success)
|
||||||
|
resolve(json);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
() => reject(),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
},
|
||||||
|
);
|
||||||
|
|
||||||
|
// Connecting to the core
|
||||||
|
if (!core.session) core.session = session;
|
|
@ -0,0 +1,27 @@
|
||||||
|
"use strict";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @name Telegram
|
||||||
|
*
|
||||||
|
* @description
|
||||||
|
* Implements actions with data of the telegram account
|
||||||
|
*
|
||||||
|
* @license http://www.wtfpl.net/ Do What The Fuck You Want To Public License
|
||||||
|
* @author Arsen Mirzaev Tatyano-Muradovich <arsen@mirzaev.sexy>
|
||||||
|
*/
|
||||||
|
export default class telegram {
|
||||||
|
/**
|
||||||
|
* @name Type of the program
|
||||||
|
*/
|
||||||
|
static type = "module";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Telegram "WebApp" API
|
||||||
|
*
|
||||||
|
* @see {@link https://core.telegram.org/bots/webapps#initializing-mini-apps}
|
||||||
|
*/
|
||||||
|
static api = window.Telegram.WebApp;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Connecting to the core
|
||||||
|
if (!core.telegram) core.telegram = telegram;
|
|
@ -1,71 +0,0 @@
|
||||||
"use strict";
|
|
||||||
|
|
||||||
// Import dependencies
|
|
||||||
import("/js/core.js").then(() =>
|
|
||||||
import("/js/damper.js").then(() =>
|
|
||||||
import("/js/telegram.js").then(() => {
|
|
||||||
const dependencies = setInterval(() => {
|
|
||||||
if (
|
|
||||||
typeof core === "function" &&
|
|
||||||
typeof core.damper === "function" &&
|
|
||||||
typeof core.telegram === "function"
|
|
||||||
) {
|
|
||||||
clearInterval(dependencies);
|
|
||||||
clearTimeout(timeout);
|
|
||||||
initialization();
|
|
||||||
}
|
|
||||||
}, 10);
|
|
||||||
const timeout = setTimeout(() => {
|
|
||||||
clearInterval(dependencies);
|
|
||||||
initialization();
|
|
||||||
}, 5000);
|
|
||||||
|
|
||||||
function initialization() {
|
|
||||||
if (typeof core.session === "undefined") {
|
|
||||||
// Not initialized
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @name Session
|
|
||||||
*
|
|
||||||
* @description
|
|
||||||
* Implements actions with sessions
|
|
||||||
*
|
|
||||||
* @memberof core
|
|
||||||
*
|
|
||||||
* @license http://www.wtfpl.net/ Do What The Fuck You Want To Public License
|
|
||||||
* @author Arsen Mirzaev Tatyano-Muradovich <arsen@mirzaev.sexy>
|
|
||||||
*/
|
|
||||||
core.session = class session {
|
|
||||||
/**
|
|
||||||
* Buffer
|
|
||||||
*/
|
|
||||||
static buffer = class buffer {
|
|
||||||
/**
|
|
||||||
* Write to the session buffer
|
|
||||||
*
|
|
||||||
* @param {string} name Name of the parameter
|
|
||||||
* @param {string} value Value of the parameter (it can be JSON)
|
|
||||||
*
|
|
||||||
* @return {void}
|
|
||||||
*/
|
|
||||||
static write(name, value) {
|
|
||||||
if (typeof name === "string" && typeof value === "string") {
|
|
||||||
//
|
|
||||||
|
|
||||||
// Send request to the server
|
|
||||||
core.request(
|
|
||||||
"/session/write",
|
|
||||||
`${name}=${value}`,
|
|
||||||
"POST",
|
|
||||||
{},
|
|
||||||
null,
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
|
||||||
};
|
|
||||||
}
|
|
||||||
}
|
|
||||||
})
|
|
||||||
)
|
|
||||||
);
|
|
|
@ -1,53 +0,0 @@
|
||||||
"use strict";
|
|
||||||
|
|
||||||
// Import dependencies
|
|
||||||
import("/js/core.js").then(() =>
|
|
||||||
import("/js/damper.js").then(() => {
|
|
||||||
const dependencies = setInterval(() => {
|
|
||||||
if (
|
|
||||||
typeof core === "function" &&
|
|
||||||
typeof core.damper === "function"
|
|
||||||
) {
|
|
||||||
clearInterval(dependencies);
|
|
||||||
clearTimeout(timeout);
|
|
||||||
initialization();
|
|
||||||
}
|
|
||||||
}, 10);
|
|
||||||
const timeout = setTimeout(() => {
|
|
||||||
clearInterval(dependencies);
|
|
||||||
initialization();
|
|
||||||
}, 5000);
|
|
||||||
|
|
||||||
function initialization() {
|
|
||||||
if (typeof core.telegram === "undefined") {
|
|
||||||
// Not initialized
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @name Telegram
|
|
||||||
*
|
|
||||||
* @description
|
|
||||||
* Implements actions with data of the telegram account
|
|
||||||
*
|
|
||||||
* @memberof core
|
|
||||||
*
|
|
||||||
* @license http://www.wtfpl.net/ Do What The Fuck You Want To Public License
|
|
||||||
* @author Arsen Mirzaev Tatyano-Muradovich <arsen@mirzaev.sexy>
|
|
||||||
*/
|
|
||||||
core.telegram = class telegram {
|
|
||||||
/**
|
|
||||||
* Telegram "WebApp" API
|
|
||||||
*
|
|
||||||
* @see {@link https://core.telegram.org/bots/webapps#initializing-mini-apps}
|
|
||||||
*/
|
|
||||||
static api = window.Telegram.WebApp;
|
|
||||||
};
|
|
||||||
|
|
||||||
/* telegram.MainButton.text =
|
|
||||||
typeof core === "object" && core.language === "ru"
|
|
||||||
? "Корзина"
|
|
||||||
: "Cart";
|
|
||||||
telegram.MainButton.show(); */
|
|
||||||
}
|
|
||||||
}
|
|
||||||
})
|
|
||||||
);
|
|
|
@ -33,8 +33,12 @@ define('CATALOG_EXAMPLE', STORAGE . DIRECTORY_SEPARATOR . 'example.xlsx');
|
||||||
// Файл в формате xlsx для импорта каталога
|
// Файл в формате xlsx для импорта каталога
|
||||||
define('CATALOG_IMPORT', STORAGE . DIRECTORY_SEPARATOR . 'import.xlsx');
|
define('CATALOG_IMPORT', STORAGE . DIRECTORY_SEPARATOR . 'import.xlsx');
|
||||||
|
|
||||||
// Ключ чат-робота Telegram
|
/**
|
||||||
define('KEY', require(SETTINGS . DIRECTORY_SEPARATOR . 'key.php'));
|
* Ключ чат-робота Telegram
|
||||||
|
* @deprecated
|
||||||
|
*/
|
||||||
|
define('KEY', require(SETTINGS . DIRECTORY_SEPARATOR . 'telegram.php'));
|
||||||
|
define('TELEGRAM_KEY', require(SETTINGS . DIRECTORY_SEPARATOR . 'telegram.php'));
|
||||||
|
|
||||||
// Initialize dependencies
|
// Initialize dependencies
|
||||||
require __DIR__ . DIRECTORY_SEPARATOR
|
require __DIR__ . DIRECTORY_SEPARATOR
|
||||||
|
@ -55,7 +59,7 @@ $config = new Config();
|
||||||
$config->setParseMode(Config::PARSE_MODE_MARKDOWN);
|
$config->setParseMode(Config::PARSE_MODE_MARKDOWN);
|
||||||
$config->useReactFileSystem(true);
|
$config->useReactFileSystem(true);
|
||||||
|
|
||||||
$bot = new Zanzara(KEY, $config);
|
$bot = new Zanzara(TELEGRAM_KEY, $config);
|
||||||
|
|
||||||
/* $bot->onUpdate(function (Context $ctx): void {
|
/* $bot->onUpdate(function (Context $ctx): void {
|
||||||
var_dump($ctx->getMessage()->getWebAppData());
|
var_dump($ctx->getMessage()->getWebAppData());
|
||||||
|
|
|
@ -1,22 +1,86 @@
|
||||||
@charset "UTF-8";
|
@charset "UTF-8";
|
||||||
|
|
||||||
main>section:is(#summary, #products) {
|
main>section:is(#summary, #products, #delivery) {
|
||||||
width: var(--width);
|
width: var(--width);
|
||||||
display: flex;
|
|
||||||
flex-direction: column;
|
|
||||||
gap: var(--gap);
|
gap: var(--gap);
|
||||||
|
overflow: hidden;
|
||||||
|
}
|
||||||
|
|
||||||
|
main>section#delivery>div.column {
|
||||||
|
padding: 1rem;
|
||||||
|
gap: var(--gap);
|
||||||
|
background-color: var(--tg-theme-secondary-bg-color);
|
||||||
|
}
|
||||||
|
|
||||||
|
main>section#delivery>div.column>div#deliveries>input {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
main>section#delivery>div.column>div#deliveries>input+label {
|
||||||
|
/* backdrop-filter: brightness(1.2); */
|
||||||
|
/* background-color: unset; */
|
||||||
|
}
|
||||||
|
|
||||||
|
main>section#delivery>div.column>div#deliveries>input+label:is(:hover, :focus) {
|
||||||
|
filter: brightness(1.1) hue-rotate(30deg);
|
||||||
|
/* filter: unset; */
|
||||||
|
/* backdrop-filter: brightness(1.4); */
|
||||||
|
}
|
||||||
|
|
||||||
|
main>section#delivery>div.column>div#deliveries>input+label:active {
|
||||||
|
filter: unset;
|
||||||
|
/* backdrop-filter: brightness(0.8); */
|
||||||
|
}
|
||||||
|
|
||||||
|
main>section#delivery>div.column>div#deliveries>input:checked+label {
|
||||||
|
filter: hue-rotate(30deg);
|
||||||
|
}
|
||||||
|
|
||||||
|
main>section#delivery>div.column>div#deliveries>input:checked+label:is(:hover, :focus) {
|
||||||
|
filter: brightness(1.1) hue-rotate(30deg);
|
||||||
|
}
|
||||||
|
|
||||||
|
main>section#delivery>div.column>div#deliveries>input:checked+label:active {
|
||||||
|
filter: brightness(0.9) hue-rotate(30deg);
|
||||||
|
}
|
||||||
|
|
||||||
|
main>section#delivery>div.column>div#address {
|
||||||
|
flex-flow: row wrap;
|
||||||
|
gap: 0.7rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
main>section#delivery>div.column>div#address>input#city {
|
||||||
|
min-width: max(6rem, 20%);
|
||||||
|
width: min(6rem, 100%);
|
||||||
|
flex-grow: 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
main>section#delivery>div.column>div#address>input#street {
|
||||||
|
min-width: max(10rem, 30%);
|
||||||
|
width: min(10rem, 100%);
|
||||||
|
flex-grow: 10;
|
||||||
|
}
|
||||||
|
|
||||||
|
main:has(section#summary.disabled:hover)>section#delivery>div {
|
||||||
|
filter: brightness(1.2);
|
||||||
}
|
}
|
||||||
|
|
||||||
main>section#summary>div {
|
main>section#summary>div {
|
||||||
|
container-type: inline-size;
|
||||||
|
container-name: summary;
|
||||||
padding-left: 1rem;
|
padding-left: 1rem;
|
||||||
display: flex;
|
|
||||||
align-items: center;
|
align-items: center;
|
||||||
gap: 0.4rem;
|
gap: 0.4rem;
|
||||||
overflow: hidden;
|
overflow: hidden;
|
||||||
|
pointer-events: auto;
|
||||||
border-radius: 1.375rem;
|
border-radius: 1.375rem;
|
||||||
background-color: var(--tg-theme-secondary-bg-color);
|
background-color: var(--tg-theme-secondary-bg-color);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
main>section#summary>div>span {
|
||||||
|
flex-shrink: 0;
|
||||||
|
}
|
||||||
|
|
||||||
main>section#summary>div>span:first-of-type {
|
main>section#summary>div>span:first-of-type {
|
||||||
/* margin-left: auto; */
|
/* margin-left: auto; */
|
||||||
}
|
}
|
||||||
|
@ -27,6 +91,19 @@ main>section#summary>div>button#order {
|
||||||
padding-left: 0.7rem;
|
padding-left: 0.7rem;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
main>section#summary.disabled,
|
||||||
|
main>section#summary>div:has(button#order:disabled),
|
||||||
|
main:not(:has(section#delivery>div.column>div#deliveries>input:checked))>section#summary>div:has(button#order:enabled) {
|
||||||
|
cursor: not-allowed;
|
||||||
|
}
|
||||||
|
|
||||||
|
main>section#summary.disabled,
|
||||||
|
main>section#summary>div>button#order:disabled,
|
||||||
|
main:not(:has(section#delivery>div.column>div#deliveries>input:checked))>section#summary>div>button#order:enabled {
|
||||||
|
pointer-events: none;
|
||||||
|
filter: grayscale(1);
|
||||||
|
}
|
||||||
|
|
||||||
main>section#products>article.product {
|
main>section#products>article.product {
|
||||||
position: relative;
|
position: relative;
|
||||||
width: 100%;
|
width: 100%;
|
||||||
|
@ -137,3 +214,9 @@ main>section#products>article.product>div>div.footer>input {
|
||||||
padding: 0 0.3rem;
|
padding: 0 0.3rem;
|
||||||
text-align: center;
|
text-align: center;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@container summary (max-width: 350px) {
|
||||||
|
main>section#summary>div>span:not(#cost) {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -180,6 +180,20 @@ input {
|
||||||
margin-left: var(--currency-offset, 0.1rem);
|
margin-left: var(--currency-offset, 0.1rem);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.rounded {
|
||||||
|
border-radius: 0.75rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.row {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: row;
|
||||||
|
}
|
||||||
|
|
||||||
|
.column {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
}
|
||||||
|
|
||||||
.unselectable {
|
.unselectable {
|
||||||
-webkit-touch-callout: none;
|
-webkit-touch-callout: none;
|
||||||
-webkit-user-select: none;
|
-webkit-user-select: none;
|
||||||
|
|
|
@ -17,8 +17,6 @@ header>nav#menu>a[type="button"] {
|
||||||
height: 3rem;
|
height: 3rem;
|
||||||
padding: unset;
|
padding: unset;
|
||||||
border-radius: 1.375rem;
|
border-radius: 1.375rem;
|
||||||
/* color: var(--unsafe-color, var(--tg-theme-button-text-color));
|
|
||||||
background-color: var(--unsafe-background-color, var(--tg-theme-button-color)); */
|
|
||||||
color: var(--tg-theme-button-text-color);
|
color: var(--tg-theme-button-text-color);
|
||||||
background-color: var(--tg-theme-button-color);
|
background-color: var(--tg-theme-button-color);
|
||||||
}
|
}
|
||||||
|
|
|
@ -133,15 +133,17 @@ section#window>div.card>p:last-of-type {
|
||||||
}
|
}
|
||||||
|
|
||||||
section#window>div.card>div.footer {
|
section#window>div.card>div.footer {
|
||||||
|
container-type: inline-size;
|
||||||
|
container-name: window-footer;
|
||||||
|
padding: 0.8rem 2.3rem;
|
||||||
display: flex;
|
display: flex;
|
||||||
flex-flow: row wrap;
|
flex-flow: row wrap;
|
||||||
align-items: baseline;
|
align-items: baseline;
|
||||||
gap: 0 0.8rem;
|
gap: 0.8rem;
|
||||||
background-color: var(--tg-theme-header-bg-color);
|
background-color: var(--tg-theme-header-bg-color);
|
||||||
}
|
}
|
||||||
|
|
||||||
section#window>div.card>div.footer>small.dimensions {
|
section#window>div.card>div.footer>small.dimensions {
|
||||||
margin-left: 1.5rem;
|
|
||||||
color: var(--tg-theme-section-header-text-color);
|
color: var(--tg-theme-section-header-text-color);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -151,7 +153,6 @@ section#window>div.card>div.footer>small.weight {
|
||||||
|
|
||||||
section#window>div.card>div.footer>p.cost {
|
section#window>div.card>div.footer>p.cost {
|
||||||
margin-left: auto;
|
margin-left: auto;
|
||||||
margin-right: 1.5rem;
|
|
||||||
font-weight: bold;
|
font-weight: bold;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -159,3 +160,20 @@ section#window>div.card>div.footer>button.buy {
|
||||||
width: 100%;
|
width: 100%;
|
||||||
height: 3.5rem;
|
height: 3.5rem;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@container window-footer (max-width: 350px) {
|
||||||
|
|
||||||
|
section#window>div.card>div.footer>small:first-of-type {
|
||||||
|
margin-left: auto;
|
||||||
|
}
|
||||||
|
|
||||||
|
section#window>div.card>div.footer>small:last-of-type {
|
||||||
|
margin-right: auto;
|
||||||
|
}
|
||||||
|
|
||||||
|
section#window>div.card>div.footer>p.cost {
|
||||||
|
margin: unset;
|
||||||
|
width: 100%;
|
||||||
|
text-align: center;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -0,0 +1,6 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
return [
|
||||||
|
'account' => '',
|
||||||
|
'secret' => ''
|
||||||
|
];
|
|
@ -8,7 +8,6 @@ namespace mirzaev\arming_bot\views;
|
||||||
use mirzaev\arming_bot\models\session,
|
use mirzaev\arming_bot\models\session,
|
||||||
mirzaev\arming_bot\models\account,
|
mirzaev\arming_bot\models\account,
|
||||||
mirzaev\arming_bot\models\settings,
|
mirzaev\arming_bot\models\settings,
|
||||||
mirzaev\arming_bot\models\cart,
|
|
||||||
mirzaev\arming_bot\models\enumerations\language,
|
mirzaev\arming_bot\models\enumerations\language,
|
||||||
mirzaev\arming_bot\models\enumerations\currency;
|
mirzaev\arming_bot\models\enumerations\currency;
|
||||||
|
|
||||||
|
@ -50,7 +49,6 @@ final class templater extends controller implements ArrayAccess
|
||||||
* @param session|null $session The object implementing a session instance from ArangoDB
|
* @param session|null $session The object implementing a session instance from ArangoDB
|
||||||
* @param account|null $account The object implementing an account instance from ArangoDB
|
* @param account|null $account The object implementing an account instance from ArangoDB
|
||||||
* @param settings|null $settings The object implementing a settings instance from ArangoDB
|
* @param settings|null $settings The object implementing a settings instance from ArangoDB
|
||||||
* @param cart|null $cart The object implementing a cart instance from ArangoDB
|
|
||||||
*
|
*
|
||||||
* @return void
|
* @return void
|
||||||
*/
|
*/
|
||||||
|
@ -58,7 +56,6 @@ final class templater extends controller implements ArrayAccess
|
||||||
?session $session = null,
|
?session $session = null,
|
||||||
?account $account = null,
|
?account $account = null,
|
||||||
?settings $settings = null,
|
?settings $settings = null,
|
||||||
?cart $cart = null
|
|
||||||
) {
|
) {
|
||||||
// Initializing an instance of twig
|
// Initializing an instance of twig
|
||||||
$this->twig = new twig(new FilesystemLoader(VIEWS));
|
$this->twig = new twig(new FilesystemLoader(VIEWS));
|
||||||
|
@ -75,7 +72,8 @@ final class templater extends controller implements ArrayAccess
|
||||||
if (!empty($account?->status())) $this->twig->addGlobal('account', $account);
|
if (!empty($account?->status())) $this->twig->addGlobal('account', $account);
|
||||||
$this->twig->addGlobal('language', $language = $account?->language ?? $session?->buffer['language'] ?? $settings?->language ?? language::en);
|
$this->twig->addGlobal('language', $language = $account?->language ?? $session?->buffer['language'] ?? $settings?->language ?? language::en);
|
||||||
$this->twig->addGlobal('currency', $currency = $account?->currency ?? $session?->buffer['currency'] ?? $settings?->currency ?? currency::usd);
|
$this->twig->addGlobal('currency', $currency = $account?->currency ?? $session?->buffer['currency'] ?? $settings?->currency ?? currency::usd);
|
||||||
$this->twig->addGlobal('cart', ['summary' => $cart->summary(currency: $currency), 'products' => $cart->products(language: $language, currency: $currency)]);
|
|
||||||
|
// @todo move functions into controllers
|
||||||
|
|
||||||
// Initialize function of dimensions formatting
|
// Initialize function of dimensions formatting
|
||||||
$this->twig->addFunction(
|
$this->twig->addFunction(
|
||||||
|
|
|
@ -6,7 +6,7 @@
|
||||||
{% if account is empty %}
|
{% if account is empty %}
|
||||||
<section id="account">
|
<section id="account">
|
||||||
<a onclick="core.account.authentication()">
|
<a onclick="core.account.authentication()">
|
||||||
<!-- {{ language == 'ru' ? "Аутентификация" : "Authentication" }} -->
|
{{ language == 'ru' ? "Аутентификация" : "Authentication" }}
|
||||||
</a>
|
</a>
|
||||||
</section>
|
</section>
|
||||||
{% else %}
|
{% else %}
|
||||||
|
@ -19,5 +19,5 @@
|
||||||
{% endblock %}
|
{% endblock %}
|
||||||
|
|
||||||
{% block js %}
|
{% block js %}
|
||||||
<script src="/js/account.js"></script>
|
<script src="/js/modules/account.js" type="module"></script>
|
||||||
{% endblock %}
|
{% endblock %}
|
||||||
|
|
|
@ -1,5 +0,0 @@
|
||||||
{% if ASDASDASDASDASDASDSD is not empty %}
|
|
||||||
<section id="" class="unselectable">
|
|
||||||
|
|
||||||
</section>
|
|
||||||
{% endif %}
|
|
|
@ -0,0 +1,25 @@
|
||||||
|
{% if deliveries is not empty %}
|
||||||
|
<section id="delivery" class="rounded column unselectable">
|
||||||
|
<div class="column">
|
||||||
|
<div id="deliveries" class="row">
|
||||||
|
{% for identifier, delivery in deliveries %}
|
||||||
|
<input id="{{ identifier }}" name="delivery" type="radio" {% if identifier==session.buffer.delivery.company %}
|
||||||
|
checked{% endif %}>
|
||||||
|
<label class="rounded" for="{{ identifier }}" type="button"
|
||||||
|
title="{{ (language.name == 'ru' ? 'Выбрать ' : 'Choose ') ~ delivery.label }}"
|
||||||
|
onclick="core.buffer.write.damper('delivery_company', '{{ identifier }}').then(() => core.delivery.check())" tabindex="5">
|
||||||
|
{{ delivery.label }}
|
||||||
|
</label>
|
||||||
|
{% endfor %}
|
||||||
|
</div>
|
||||||
|
<div id="address" class="row">
|
||||||
|
<input id="city" placeholder="{{ language.name == 'ru' ? 'Город' : 'City' }}"
|
||||||
|
value="{{ session.buffer.delivery.city ?? account.buffer.delivery.city }}"
|
||||||
|
onkeydown="core.buffer.write.damper('delivery_city', this.value).then(() => core.delivery.check())" tabindex="6" />
|
||||||
|
<input id="street" placeholder="{{ language.name == 'ru' ? 'Улица' : 'Street' }}"
|
||||||
|
value="{{ session.buffer.delivery.street ?? session.buffer.delivery.street }}"
|
||||||
|
onkeydown="core.buffer.write.damper('delivery_street', this.value).then(() => core.delivery.check())" tabindex="6" />
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</section>
|
||||||
|
{% endif %}
|
|
@ -1,5 +1,5 @@
|
||||||
{% macro card(product, amount) %}
|
{% macro card(product, amount) %}
|
||||||
<article id="{{ product._id }}" class="product unselectable" data-product-identifier="{{ product.identifier }}"
|
<article id="{{ product._id }}" class="product" data-product-identifier="{{ product.identifier }}"
|
||||||
data-product-amount="{{ amount }}" {% if amount> 0 %} style="--hue-rotate-offset: {{ amount }}0deg;"{% endif %}>
|
data-product-amount="{{ amount }}" {% if amount> 0 %} style="--hue-rotate-offset: {{ amount }}0deg;"{% endif %}>
|
||||||
<a data-product="cover" href="?product={{ product.identifier }}" onclick="return core.catalog.product(this);"
|
<a data-product="cover" href="?product={{ product.identifier }}" onclick="return core.catalog.product(this);"
|
||||||
onkeydown="event.keyCode === 13 && core.catalog.product(this)" tabindex="10">
|
onkeydown="event.keyCode === 13 && core.catalog.product(this)" tabindex="10">
|
||||||
|
@ -40,8 +40,9 @@
|
||||||
</article>
|
</article>
|
||||||
{% endmacro %}
|
{% endmacro %}
|
||||||
{% if cart.products is not empty %}
|
{% if cart.products is not empty %}
|
||||||
<section id="products" class="unselectable">
|
<section id="products" class="column unselectable">
|
||||||
{% for product in cart.products %}
|
{% for product in cart.products %}
|
||||||
|
{{ product.summary }}
|
||||||
{{ _self.card(product.document, product.amount) }}
|
{{ _self.card(product.document, product.amount) }}
|
||||||
{% endfor %}
|
{% endfor %}
|
||||||
</section>
|
</section>
|
||||||
|
|
|
@ -1,10 +1,13 @@
|
||||||
{% if cart.products is not empty %}
|
{% if cart.products is not empty %}
|
||||||
<section id="summary" class="unselectable">
|
<section id="summary"
|
||||||
<div>
|
class="column {% if delivery is empty or delivery.city is empty or delivery.street is empty %}disabled{% endif %} unselectable"
|
||||||
|
{% if delivery is empty %}title="{{ language.name == " ru" ? "Выберите тип доставки" : "Choose delivery type" }}"{%
|
||||||
|
endif %}>
|
||||||
|
<div class="row">
|
||||||
<span id="amount">{{ cart.summary.amount ?? 0 }}</span>
|
<span id="amount">{{ cart.summary.amount ?? 0 }}</span>
|
||||||
<span>{{ language.name == "ru" ? "товаров на сумму" : "products worth" }}</span>
|
<span>{{ language.name == "ru" ? "товаров на сумму" : "products worth" }}</span>
|
||||||
<span id="cost" class="cost currency">{{ cart.summary.cost ?? 0 }}</span>
|
<span id="cost" class="cost currency">{{ cart.summary.cost ?? 0 }}</span>
|
||||||
<button id="order" onclick="core.cart.order(this)"
|
<button id="order" onclick="core.cart.order(this)" {% if delivery is empty %} disabled="true" {% endif %}
|
||||||
title="{{ language.name == 'ru' ? 'Оформить заказ' : 'Place an order' }}"><i class="icon arrow"></i></button>
|
title="{{ language.name == 'ru' ? 'Оформить заказ' : 'Place an order' }}"><i class="icon arrow"></i></button>
|
||||||
</div>
|
</div>
|
||||||
</section>
|
</section>
|
||||||
|
|
|
@ -12,13 +12,15 @@
|
||||||
{% endblock %}
|
{% endblock %}
|
||||||
|
|
||||||
{% block main %}
|
{% block main %}
|
||||||
<h2 class="unselectable">{{ h2 }}</h2>
|
<h2 id="title" class="unselectable">{{ h2 }}</h2>
|
||||||
|
{% include "/themes/default/cart/elements/delivery.html" %}
|
||||||
{% include "/themes/default/cart/elements/summary.html" %}
|
{% include "/themes/default/cart/elements/summary.html" %}
|
||||||
{% include "/themes/default/cart/elements/products.html" %}
|
{% include "/themes/default/cart/elements/products.html" %}
|
||||||
{% endblock %}
|
{% endblock %}
|
||||||
|
|
||||||
{% block js %}
|
{% block js %}
|
||||||
{{ parent() }}
|
{{ parent() }}
|
||||||
<script src="/js/cart.js"></script>
|
<script src="/js/modules/delivery.js" type="module"></script>
|
||||||
<script src="/js/hotline.js"></script>
|
<script src="/js/modules/cart.js" type="module"></script>
|
||||||
|
<script src="/js/modules/hotline.js" type="module"></script>
|
||||||
{% endblock %}
|
{% endblock %}
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
{% if filters is not empty %}
|
{% if filters is not empty %}
|
||||||
<section id="filters" class="unselectble">
|
<section id="filters" class="unselectble">
|
||||||
<section class="unselectable" data-type="select" tabindex="4">
|
<section class="unselectable" data-type="select" tabindex="4">
|
||||||
{% set buffer_brand = account.buffer.catalog.filters.brand ?? session.buffer.catalog.filters.brand %}
|
{% set buffer_brand = session.buffer.catalog.filters.brand ?? account.buffer.catalog.filters.brand %}
|
||||||
<input name="brand" type="radio" id="brand_title" {% if buffer_brand is empty %} checked{% endif %}>
|
<input name="brand" type="radio" id="brand_title" {% if buffer_brand is empty %} checked{% endif %}>
|
||||||
<label for="brand_title" type="button" onclick="core.catalog.parameters.set('brand', null); core.catalog.search(event)">
|
<label for="brand_title" type="button" onclick="core.catalog.parameters.set('brand', null); core.catalog.search(event)">
|
||||||
{{ language.name == 'ru' ? 'Бренд' : 'Brand' }}
|
{{ language.name == 'ru' ? 'Бренд' : 'Brand' }}
|
||||||
|
|
|
@ -16,7 +16,6 @@ product.dimensions.y, product.dimensions.z, ' ') ~ ' ' ~ product.weight ~ 'г' %
|
||||||
<button data-product-button="toggle" onclick="core.cart.toggle(this, document.getElementById('{{ product.getId() }}'))" tabindex="15">
|
<button data-product-button="toggle" onclick="core.cart.toggle(this, document.getElementById('{{ product.getId() }}'))" tabindex="15">
|
||||||
<span data-product-parameter="amount">{{ amount }}</span>
|
<span data-product-parameter="amount">{{ amount }}</span>
|
||||||
<span class="cost currency" data-product-parameter="cost">{{ product.cost }}</span>
|
<span class="cost currency" data-product-parameter="cost">{{ product.cost }}</span>
|
||||||
<span data-product-parameter="currency">{{ currency.symbol }}</span>
|
|
||||||
</button>
|
</button>
|
||||||
<button data-product-button="write" onclick="core.cart.write(this, document.getElementById('{{ product.getId() }}'), 1)" title="{{ language.name == 'ru' ? 'Увеличить' : 'Increase' }}"><i class="icon small plus"></i></button>
|
<button data-product-button="write" onclick="core.cart.write(this, document.getElementById('{{ product.getId() }}'), 1)" title="{{ language.name == 'ru' ? 'Увеличить' : 'Increase' }}"><i class="icon small plus"></i></button>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
<search id="search">
|
<search id="search">
|
||||||
<label class="unselectable"><i class="icon search"></i></label>
|
<label class="unselectable"><i class="icon search"></i></label>
|
||||||
{% set buffer_search = account.buffer.catalog.search.text ?? session.buffer.catalog.search.text %}
|
{% set buffer_search = session.buffer.catalog.search.text ?? account.buffer.catalog.search.text %}
|
||||||
<input placeholder="{{ language.name == 'ru' ? 'Поиск по каталогу' : 'Search in the catalog' }}" type="search" tabindex="1"
|
<input placeholder="{{ language.name == 'ru' ? 'Поиск по каталогу' : 'Search in the catalog' }}" type="search" tabindex="1"
|
||||||
onkeyup="event.keyCode === 9 || core.catalog.parameters.set('text', this.value); core.catalog.search(event, this)"
|
onkeyup="event.keyCode === 9 || core.catalog.parameters.set('text', this.value); core.catalog.search(event, this)"
|
||||||
{% if buffer_search is not empty %} value="{{ buffer_search }}" {% endif %} />
|
{% if buffer_search is not empty %} value="{{ buffer_search }}" {% endif %} />
|
||||||
|
|
|
@ -12,7 +12,7 @@
|
||||||
{% endblock %}
|
{% endblock %}
|
||||||
|
|
||||||
{% block main %}
|
{% block main %}
|
||||||
<h2 class="unselectable">{{ h2 }}</h2>
|
<h2 id="title" class="unselectable">{{ h2 }}</h2>
|
||||||
{% include "/themes/default/catalog/elements/search.html" %}
|
{% include "/themes/default/catalog/elements/search.html" %}
|
||||||
{% include "/themes/default/catalog/elements/categories.html" %}
|
{% include "/themes/default/catalog/elements/categories.html" %}
|
||||||
{% include "/themes/default/catalog/elements/filters.html" %}
|
{% include "/themes/default/catalog/elements/filters.html" %}
|
||||||
|
@ -21,7 +21,7 @@
|
||||||
|
|
||||||
{% block js %}
|
{% block js %}
|
||||||
{{ parent() }}
|
{{ parent() }}
|
||||||
<script src="/js/catalog.js"></script>
|
<script src="/js/modules/catalog.js" type="module"></script>
|
||||||
<script src="/js/cart.js"></script>
|
<script src="/js/modules/cart.js" type="module"></script>
|
||||||
<script src="/js/hotline.js"></script>
|
<script src="/js/hotline.js" type="module"></script>
|
||||||
{% endblock %}
|
{% endblock %}
|
||||||
|
|
|
@ -10,5 +10,5 @@
|
||||||
{% endblock %}
|
{% endblock %}
|
||||||
|
|
||||||
{% block js %}
|
{% block js %}
|
||||||
<script src="/js/connection.js"></script>
|
<script src="/js/modules/connection.js" type="module"></script>
|
||||||
{% endblock %}
|
{% endblock %}
|
||||||
|
|
|
@ -1,38 +1,20 @@
|
||||||
{% block js %}
|
{% block js %}
|
||||||
<script src="https://telegram.org/js/telegram-web-app.js"></script>
|
<script src="https://telegram.org/js/telegram-web-app.js"></script>
|
||||||
|
<script src="/js/modules/damper.js" type="module"></script>
|
||||||
<script src="/js/core.js"></script>
|
<script src="/js/core.js"></script>
|
||||||
<script src="/js/damper.js"></script>
|
<script src="/js/modules/loader.js" type="module"></script>
|
||||||
<script src="/js/loader.js"></script>
|
<script src="/js/modules/telegram.js" type="module"></script>
|
||||||
<script src="/js/telegram.js"></script>
|
<script src="/js/modules/session.js" type="module"></script>
|
||||||
<script src="/js/session.js"></script>
|
|
||||||
<script src="/js/authentication.js"></script>
|
<script src="/js/authentication.js"></script>
|
||||||
{% if javascript is not empty %}
|
{% if javascript is not empty %}
|
||||||
<script>
|
<script>
|
||||||
import("/js/core.js").then(() =>
|
core.modules.connect("damper").then(() => {
|
||||||
import("/js/damper.js").then(() => {
|
|
||||||
const dependencies = setInterval(() => {
|
|
||||||
if (
|
|
||||||
typeof core === "function" &&
|
|
||||||
typeof core.damper === "function"
|
|
||||||
) {
|
|
||||||
clearInterval(dependencies);
|
|
||||||
clearTimeout(timeout);
|
|
||||||
initialization();
|
|
||||||
}
|
|
||||||
}, 10);
|
|
||||||
const timeout = setTimeout(() => {
|
|
||||||
clearInterval(dependencies);
|
|
||||||
initialization();
|
|
||||||
}, 5000);
|
|
||||||
|
|
||||||
function initialization() {
|
|
||||||
let _window;
|
let _window;
|
||||||
|
|
||||||
{% for code in javascript %}
|
{% for code in javascript %}
|
||||||
{{ code|raw }}
|
{{ code|raw }}
|
||||||
{% endfor %}
|
{% endfor %}
|
||||||
}
|
});
|
||||||
})
|
|
||||||
);
|
|
||||||
</script>
|
</script>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
{% endblock %}
|
{% endblock %}
|
||||||
|
|
|
@ -12,7 +12,7 @@
|
||||||
{% for button in menu %}
|
{% for button in menu %}
|
||||||
<a href='{{ button.urn }}' onclick="return core.loader.load('{{ button.urn }}');" type="button" class="unselectable"
|
<a href='{{ button.urn }}' onclick="return core.loader.load('{{ button.urn }}');" type="button" class="unselectable"
|
||||||
title="{{ button.name }}" {% if button.style %}
|
title="{{ button.name }}" {% if button.style %}
|
||||||
style="{% for parameter, value in button.style %}{{ parameter ~ ': ' ~ value ~ '; ' }}{% endfor %}" {% endif %}">
|
style="{% for parameter, value in button.style %}{{ parameter ~ ': ' ~ value ~ '; ' }}{% endfor %}" {% endif %}>
|
||||||
{% if button.icon %}
|
{% if button.icon %}
|
||||||
<i class="icon {{ button.icon.class }}" {% if button.icon.style %}
|
<i class="icon {{ button.icon.class }}" {% if button.icon.style %}
|
||||||
style="{% for parameter, value in button.icon.style %}{{ parameter ~ ': ' ~ value ~ '; ' }}{% endfor %}" {% endif
|
style="{% for parameter, value in button.icon.style %}{{ parameter ~ ': ' ~ value ~ '; ' }}{% endfor %}" {% endif
|
||||||
|
|
|
@ -0,0 +1,11 @@
|
||||||
|
{% if deliveries is not empty %}
|
||||||
|
<section id="deliveries" class="unselectable">
|
||||||
|
{% for identifier, delivery in deliveries %}
|
||||||
|
<div id="{{ identifier }}">
|
||||||
|
<h4>{{ identifier[:1]|upper ~ identifier[1:] }}</h4>
|
||||||
|
<button onclick="core.delivery.choose(this, '{{ identifier }}')"
|
||||||
|
title="{{ language.name == 'ru' ? 'Выбрать {{ identifier }}' : 'Choose {{ identifier }}' }}"></button>
|
||||||
|
</div>
|
||||||
|
{% endfor %}
|
||||||
|
</section>
|
||||||
|
{% endif %}
|
|
@ -0,0 +1,11 @@
|
||||||
|
{% if cart.products is not empty %}
|
||||||
|
<section id="summary" class="unselectable">
|
||||||
|
<div>
|
||||||
|
<span id="amount">{{ cart.summary.amount ?? 0 }}</span>
|
||||||
|
<span>{{ language.name == "ru" ? "товаров на сумму" : "products worth" }}</span>
|
||||||
|
<span id="cost" class="cost currency">{{ cart.summary.cost ?? 0 }}</span>
|
||||||
|
<button id="order" onclick="core.cart.order(this)"
|
||||||
|
title="{{ language.name == 'ru' ? 'Оформить заказ' : 'Place an order' }}"><i class="icon arrow"></i></button>
|
||||||
|
</div>
|
||||||
|
</section>
|
||||||
|
{% endif %}
|
|
@ -0,0 +1,24 @@
|
||||||
|
{% extends "/themes/default/index.html" %}
|
||||||
|
|
||||||
|
{% block css %}
|
||||||
|
{{ parent() }}
|
||||||
|
<link type="text/css" rel="stylesheet" href="/themes/{{ theme }}/css/cart.css" />
|
||||||
|
<link type="text/css" rel="stylesheet" href="/themes/{{ theme }}/css/icons/trash.css" />
|
||||||
|
<link type="text/css" rel="stylesheet" href="/themes/{{ theme }}/css/icons/list_add.css" />
|
||||||
|
<link type="text/css" rel="stylesheet" href="/themes/{{ theme }}/css/icons/shopping_cart.css" />
|
||||||
|
<link type="text/css" rel="stylesheet" href="/themes/{{ theme }}/css/icons/plus.css" />
|
||||||
|
<link type="text/css" rel="stylesheet" href="/themes/{{ theme }}/css/icons/minus.css" />
|
||||||
|
<link type="text/css" rel="stylesheet" href="/themes/{{ theme }}/css/icons/arrow.css" />
|
||||||
|
{% endblock %}
|
||||||
|
|
||||||
|
{% block main %}
|
||||||
|
<h2 id="title" class="unselectable">{{ h2 }}</h2>
|
||||||
|
{% include "/themes/default/cart/elements/delivery.html" %}
|
||||||
|
{% include "/themes/default/cart/elements/summary.html" %}
|
||||||
|
{% endblock %}
|
||||||
|
|
||||||
|
{% block js %}
|
||||||
|
{{ parent() }}
|
||||||
|
<script src="/js/modules/cart.js" type="module"></script>
|
||||||
|
<script src="/js/modules/hotline.js" type="module"></script>
|
||||||
|
{% endblock %}
|
Loading…
Reference in New Issue