THE JAVASCRIPT SYSTEM TOTAL REBUILD
This commit is contained in:
parent
b07d60d8e5
commit
cf0e32e954
|
@ -28,7 +28,10 @@
|
|||
"twig/extra-bundle": "^3.7",
|
||||
"twig/intl-extra": "^3.10",
|
||||
"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": {
|
||||
"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
|
||||
{
|
||||
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) {
|
||||
// Iterate over parameters
|
||||
|
||||
// Validation of the parameter
|
||||
// Validation of the parameter value
|
||||
if (mb_strlen($value) > 4096) continue;
|
||||
|
||||
// Convert name to multidimensional array
|
||||
foreach (array_reverse(explode('_', $name)) as $key) $parameter = [$key => $parameter ?? json_validate($value) ? json_decode($value, true, 10) : $value];
|
||||
// Declaring the buffer of deserialized parameter
|
||||
$parameter = null;
|
||||
|
||||
// Write data of to the buffer parameter in the implement object of account document from ArangoDB
|
||||
$this->account->buffer = $parameter + $this->account->buffer ?? [];
|
||||
// Deserializing name to multidimensional array
|
||||
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
|
||||
{
|
||||
/**
|
||||
* Instance of the cart
|
||||
*/
|
||||
protected readonly ?model $cart;
|
||||
|
||||
/**
|
||||
* 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') {
|
||||
// GET request
|
||||
|
||||
|
@ -135,93 +156,100 @@ final class cart extends core
|
|||
if ($product instanceof product) {
|
||||
// Initialized the product
|
||||
|
||||
// Initializing the buffer with amount of the product in the cart
|
||||
$amount = $this->cart->count(product: $product, limit: 100, errors: $this->errors['cart']) ?? 0;
|
||||
// Initializing the cart
|
||||
$this->cart = $this->account?->cart() ?? $this->session?->cart();
|
||||
|
||||
if ($this->cart instanceof model) {
|
||||
// Initialized the cart
|
||||
|
||||
// Validating @todo add throwing errors
|
||||
$type = null;
|
||||
if (isset($parameters['type']) && preg_match('/[\w]+/', urldecode($parameters['type']), $matches)) $type = $matches[0];
|
||||
// Initializing the buffer with amount of the product in the cart
|
||||
$amount = $this->cart->count(product: $product, limit: 100, errors: $this->errors['cart']) ?? 0;
|
||||
|
||||
if (isset($type)) {
|
||||
// Received and validated type of action with the product
|
||||
if ($this->cart instanceof model) {
|
||||
// Initialized the cart
|
||||
|
||||
if ($type === 'toggle') {
|
||||
// Write the product to the cart if is not in the cart and vice versa
|
||||
// Validating @todo add throwing errors
|
||||
$type = null;
|
||||
if (isset($parameters['type']) && preg_match('/[\w]+/', urldecode($parameters['type']), $matches)) $type = $matches[0];
|
||||
|
||||
if ($amount > 0) {
|
||||
// The cart has the product
|
||||
if (isset($type)) {
|
||||
// Received and validated type of action with the product
|
||||
|
||||
// Deleting the product from the cart
|
||||
$this->cart->delete(product: $product, amount: $amount, errors: $this->errors['cart']);
|
||||
if ($type === 'toggle') {
|
||||
// Write the product to the cart if is not in the cart and vice versa
|
||||
|
||||
// Reinitializing the buffer with amount of the product in the cart
|
||||
$amount = 0;
|
||||
if ($amount > 0) {
|
||||
// The cart has the product
|
||||
|
||||
// Deleting the product from the cart
|
||||
$this->cart->delete(product: $product, amount: $amount, errors: $this->errors['cart']);
|
||||
|
||||
// Reinitializing the buffer with amount of the product in the cart
|
||||
$amount = 0;
|
||||
} else {
|
||||
// The cart has no the product
|
||||
|
||||
// Writing the product to the cart
|
||||
$this->cart->write(product: $product, amount: 1, errors: $this->errors['cart']);
|
||||
|
||||
// Reinitializing the buffer with amount of the product in the cart
|
||||
$amount = 1;
|
||||
}
|
||||
} else {
|
||||
// The cart has no the product
|
||||
// Received not the "toggle" command
|
||||
|
||||
// Writing the product to the cart
|
||||
$this->cart->write(product: $product, amount: 1, errors: $this->errors['cart']);
|
||||
// Validating @todo add throwing errors
|
||||
$_amount = null;
|
||||
if (isset($parameters['amount']) && preg_match('/[\d]+/', urldecode($parameters['amount']), $matches)) $_amount = (int) $matches[0];
|
||||
|
||||
// Reinitializing the buffer with amount of the product in the cart
|
||||
$amount = 1;
|
||||
}
|
||||
} else {
|
||||
// Received not the "toggle" command
|
||||
if (isset($_amount)) {
|
||||
// Received and validated amount parameter for action with the product
|
||||
|
||||
// Validating @todo add throwing errors
|
||||
$_amount = null;
|
||||
if (isset($parameters['amount']) && preg_match('/[\d]+/', urldecode($parameters['amount']), $matches)) $_amount = (int) $matches[0];
|
||||
if ($type === 'write') {
|
||||
// Increase amount of the product in the cart
|
||||
|
||||
if (isset($_amount)) {
|
||||
// Received and validated amount parameter for action with the product
|
||||
if ($amount + $_amount < 101) {
|
||||
// Validated amount to wrting
|
||||
|
||||
if ($type === 'write') {
|
||||
// Increase amount of the product in the cart
|
||||
// Writing the product to the cart
|
||||
$this->cart->write(product: $product, amount: $_amount, errors: $this->errors['cart']);
|
||||
|
||||
if ($amount + $_amount < 101) {
|
||||
// Validated amount to wrting
|
||||
// Reinitialize the buffer with amount of the product in the cart
|
||||
$amount += $_amount;
|
||||
}
|
||||
} else if ($type === 'delete') {
|
||||
// Decrease amount of the product in the cart
|
||||
|
||||
// Writing the product to the cart
|
||||
$this->cart->write(product: $product, amount: $_amount, errors: $this->errors['cart']);
|
||||
|
||||
// Reinitialize the buffer with amount of the product in the cart
|
||||
$amount += $_amount;
|
||||
}
|
||||
} else if ($type === 'delete') {
|
||||
// Decrease amount of the product in the cart
|
||||
|
||||
if ($amount - $_amount > -1) {
|
||||
// Validated amount to deleting
|
||||
|
||||
// Deleting the product from the cart
|
||||
$this->cart->delete(product: $product, amount: $_amount, errors: $this->errors['cart']);
|
||||
|
||||
// Reinitialize the buffer with amount of the product in the cart
|
||||
$amount -= $_amount;
|
||||
}
|
||||
} else if ($type === 'set') {
|
||||
// Set amount of the product in the cart
|
||||
|
||||
if ($_amount > -1 && $_amount < 101) {
|
||||
// Validated amount to setting
|
||||
|
||||
if ($_amount > $amount) {
|
||||
// Requested amount more than actual amount of the product in the cart
|
||||
|
||||
// Writing the product from the cart
|
||||
$this->cart->write(product: $product, amount: $_amount - $amount, errors: $this->errors['cart']);
|
||||
} else {
|
||||
// Requested amount less than actual amount of the product in the cart
|
||||
if ($amount - $_amount > -1) {
|
||||
// Validated amount to deleting
|
||||
|
||||
// Deleting the product from the cart
|
||||
$this->cart->delete(product: $product, amount: $amount - $_amount, errors: $this->errors['cart']);
|
||||
}
|
||||
$this->cart->delete(product: $product, amount: $_amount, errors: $this->errors['cart']);
|
||||
|
||||
// Reinitializing the buffer with amount of the product in the cart
|
||||
$amount = $_amount;
|
||||
// Reinitialize the buffer with amount of the product in the cart
|
||||
$amount -= $_amount;
|
||||
}
|
||||
} else if ($type === 'set') {
|
||||
// Set amount of the product in the cart
|
||||
|
||||
if ($_amount > -1 && $_amount < 101) {
|
||||
// Validated amount to setting
|
||||
|
||||
if ($_amount > $amount) {
|
||||
// Requested amount more than actual amount of the product in the cart
|
||||
|
||||
// Writing the product from the cart
|
||||
$this->cart->write(product: $product, amount: $_amount - $amount, errors: $this->errors['cart']);
|
||||
} else {
|
||||
// Requested amount less than actual amount of the product in the cart
|
||||
|
||||
// Deleting the product from the cart
|
||||
$this->cart->delete(product: $product, amount: $amount - $_amount, errors: $this->errors['cart']);
|
||||
}
|
||||
|
||||
// Reinitializing the buffer with amount of the product in the cart
|
||||
$amount = $_amount;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -272,35 +300,42 @@ final class cart extends core
|
|||
if ($_SERVER['REQUEST_METHOD'] === 'POST') {
|
||||
// POST request
|
||||
|
||||
// Initializing summary data of the cart
|
||||
$summary = $this->cart?->summary(currency: $this->currency, errors: $this->errors['cart']);
|
||||
// Initializing the cart
|
||||
$this->cart = $this->account?->cart() ?? $this->session?->cart();
|
||||
|
||||
// Initializing response headers
|
||||
header('Content-Type: application/json');
|
||||
header('Content-Encoding: none');
|
||||
header('X-Accel-Buffering: no');
|
||||
if ($this->cart instanceof model) {
|
||||
// Initialized the cart
|
||||
|
||||
// Initializing of the output buffer
|
||||
ob_start();
|
||||
// Initializing summary data of the cart
|
||||
$summary = $this->cart?->summary(currency: $this->currency, errors: $this->errors['cart']);
|
||||
|
||||
// Generating the reponse
|
||||
echo json_encode(
|
||||
[
|
||||
'cost' => $summary['cost'] ?? 0,
|
||||
'amount' => $summary['amount'] ?? 0,
|
||||
'errors' => $this->errors
|
||||
]
|
||||
);
|
||||
// Initializing response headers
|
||||
header('Content-Type: application/json');
|
||||
header('Content-Encoding: none');
|
||||
header('X-Accel-Buffering: no');
|
||||
|
||||
// Initializing a response headers
|
||||
header('Content-Length: ' . ob_get_length());
|
||||
// Initializing of the output buffer
|
||||
ob_start();
|
||||
|
||||
// Sending and deinitializing of the output buffer
|
||||
ob_end_flush();
|
||||
flush();
|
||||
// Generating the reponse
|
||||
echo json_encode(
|
||||
[
|
||||
'cost' => $summary['cost'] ?? 0,
|
||||
'amount' => $summary['amount'] ?? 0,
|
||||
'errors' => $this->errors
|
||||
]
|
||||
);
|
||||
|
||||
// Exit (success)
|
||||
return null;
|
||||
// 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)
|
||||
|
|
|
@ -53,7 +53,7 @@ final class catalog extends core
|
|||
filter: "d.identifier == @identifier && d.deleted != true && d.hidden != true",
|
||||
sort: 'd.created DESC',
|
||||
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,
|
||||
currency: $this->currency,
|
||||
parameters: ['identifier' => $product],
|
||||
|
@ -186,7 +186,7 @@ final class catalog extends core
|
|||
if (isset($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(
|
||||
[
|
||||
'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(
|
||||
[
|
||||
'catalog' => [
|
||||
|
@ -296,7 +296,7 @@ final class catalog extends core
|
|||
) ?? 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
|
||||
|
||||
// Search for filters and write to the buffer of global variables of view templater
|
||||
|
@ -355,7 +355,7 @@ final class catalog extends core
|
|||
sprintf(
|
||||
<<<javascript
|
||||
if (typeof _window === 'undefined') {
|
||||
_window = setTimeout(() => core.catalog.product_system('%s'), 500);
|
||||
_window = setTimeout(() => core.catalog.product.system('%s'), 500);
|
||||
}
|
||||
javascript,
|
||||
$this->view->product['identifier']
|
||||
|
|
|
@ -138,15 +138,11 @@ class core extends controller
|
|||
// Initializing of the currency
|
||||
$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
|
||||
$this->view = new templater(
|
||||
session: $this->session,
|
||||
account: $this->account,
|
||||
settings: $this->settings,
|
||||
cart: $this->cart
|
||||
settings: $this->settings
|
||||
);
|
||||
|
||||
// @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;
|
||||
}
|
||||
}
|
|
@ -161,29 +161,36 @@ final class session extends core
|
|||
* @param array $parameters Parameters of the request (POST + GET)
|
||||
*
|
||||
* @return void
|
||||
*
|
||||
* @todo переделать под trait buffer
|
||||
*
|
||||
* @todo переделать под trait buffer
|
||||
*/
|
||||
public function write(array $parameters = []): void
|
||||
{
|
||||
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) {
|
||||
// Iterate over parameters
|
||||
|
||||
// Validation of the parameter
|
||||
// Validation of the parameter value
|
||||
if (mb_strlen($value) > 4096) continue;
|
||||
|
||||
// Convert name to multidimensional array
|
||||
foreach (array_reverse(explode('_', $name)) as $key) $parameter = [$key => $parameter ?? json_validate($value) ? json_decode($value, true, 10) : $value];
|
||||
// Declaring the buffer of deserialized parameter
|
||||
$parameter = null;
|
||||
|
||||
// Write data of to the buffer parameter in the implement object of session document from ArangoDB
|
||||
$this->session->buffer = $parameter + ($this->session->buffer ?? []);
|
||||
// Deserializing name to multidimensional array
|
||||
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
|
||||
document::update($this->session->__document(), $this->errors['session']);
|
||||
// Write to the session document from ArangoDB
|
||||
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)
|
||||
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 ' . reservation::TYPE . ' collection: ' . reservation::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;
|
||||
|
||||
// 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
|
||||
use ArangoDBClient\Document as _document;
|
||||
|
@ -47,12 +49,19 @@ trait buffer
|
|||
if (collection::initialize(static::COLLECTION, static::TYPE, errors: $errors)) {
|
||||
// Initialized the collection
|
||||
|
||||
// The instance of the document from ArangoDB is initialized?
|
||||
isset($this->document) || throw new exception('The instance of the sessoin document from ArangoDB is not initialized');
|
||||
// Is the instance of the document from ArangoDB are 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
|
||||
$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)
|
||||
return document::update($this->document, errors: $errors);
|
||||
} else throw new exception('Failed to initialize ' . static::TYPE . ' collection: ' . static::COLLECTION);
|
||||
|
|
|
@ -47,6 +47,7 @@ $router
|
|||
->write('/account/write', 'account', 'write', 'POST')
|
||||
->write('/session/write', 'session', 'write', 'POST')
|
||||
->write('/session/connect/telegram', 'session', 'telegram', 'POST')
|
||||
->write('/cdek/calculate', 'deliveries\\cdek', 'calculate', 'POST')
|
||||
/* ->write('/category/$identifier', 'catalog', 'index', 'POST') */
|
||||
/* ->write('/category', 'catalog', 'index', '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,45 +1,20 @@
|
|||
"use strict";
|
||||
|
||||
// Import dependencies
|
||||
import("/js/core.js").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);
|
||||
core.modules.connect(["session", "account", "telegram"])
|
||||
.then(() => {
|
||||
//
|
||||
const { initData, initDataUnsafe, ...data } = core.telegram.api;
|
||||
|
||||
function initialization() {
|
||||
//
|
||||
const { initData, initDataUnsafe, ...data } = core.telegram.api;
|
||||
//
|
||||
core.session.buffer.write("telegram_program", JSON.stringify(data));
|
||||
|
||||
//
|
||||
core.session.buffer.write("telegram_program", JSON.stringify(data));
|
||||
if (core.telegram.api.initData.length > 0) {
|
||||
//
|
||||
|
||||
if (core.telegram.api.initData.length > 0) {
|
||||
//
|
||||
//
|
||||
core.account.authentication();
|
||||
}
|
||||
|
||||
//
|
||||
core.account.authentication();
|
||||
}
|
||||
|
||||
//
|
||||
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
|
||||
*
|
||||
|
@ -9,7 +7,7 @@
|
|||
* @license http://www.wtfpl.net/ Do What The Fuck You Want To Public License
|
||||
* @author Arsen Mirzaev Tatyano-Muradovich <arsen@mirzaev.sexy>
|
||||
*/
|
||||
const core = class core {
|
||||
class core {
|
||||
// Domain
|
||||
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 {
|
||||
/**
|
||||
* Write to buffers
|
||||
* @name Write to buffers
|
||||
*
|
||||
* @description
|
||||
* Write to buffers (interface)
|
||||
*
|
||||
* @param {string} name Name of the parameter
|
||||
* @param {string} value Value of the parameter (it can be JSON)
|
||||
*
|
||||
* @return {void}
|
||||
* @return {bool} Execution completed with an error?
|
||||
*/
|
||||
static write(name, value) {
|
||||
if (typeof this.session === "function") {
|
||||
// Initialized the session implement object
|
||||
core.modules.connect("damper").then(
|
||||
() => {
|
||||
// Imported the damper module
|
||||
|
||||
// Write to the session buffer
|
||||
core.session.buffer.write(name, value);
|
||||
}
|
||||
// Execute under damper
|
||||
this.write.damper(name, value);
|
||||
},
|
||||
() => {
|
||||
// Not imported the damper module
|
||||
|
||||
if (typeof this.account === "function") {
|
||||
// Initialized the account implement object
|
||||
// Execute
|
||||
this.write.system(name, value);
|
||||
},
|
||||
);
|
||||
|
||||
// Write to the account buffer
|
||||
core.account.buffer.write(name, value);
|
||||
}
|
||||
// Exit (success)
|
||||
return false;
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -274,4 +292,112 @@ const core = class core {
|
|||
},
|
||||
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);
|
||||
}
|
||||
});
|
||||
});
|
||||
};
|
||||
}
|
||||
}
|
||||
});
|
File diff suppressed because it is too large
Load Diff
|
@ -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 для импорта каталога
|
||||
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
|
||||
require __DIR__ . DIRECTORY_SEPARATOR
|
||||
|
@ -55,7 +59,7 @@ $config = new Config();
|
|||
$config->setParseMode(Config::PARSE_MODE_MARKDOWN);
|
||||
$config->useReactFileSystem(true);
|
||||
|
||||
$bot = new Zanzara(KEY, $config);
|
||||
$bot = new Zanzara(TELEGRAM_KEY, $config);
|
||||
|
||||
/* $bot->onUpdate(function (Context $ctx): void {
|
||||
var_dump($ctx->getMessage()->getWebAppData());
|
||||
|
|
|
@ -1,22 +1,86 @@
|
|||
@charset "UTF-8";
|
||||
|
||||
main>section:is(#summary, #products) {
|
||||
main>section:is(#summary, #products, #delivery) {
|
||||
width: var(--width);
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
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 {
|
||||
container-type: inline-size;
|
||||
container-name: summary;
|
||||
padding-left: 1rem;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 0.4rem;
|
||||
overflow: hidden;
|
||||
pointer-events: auto;
|
||||
border-radius: 1.375rem;
|
||||
background-color: var(--tg-theme-secondary-bg-color);
|
||||
}
|
||||
|
||||
main>section#summary>div>span {
|
||||
flex-shrink: 0;
|
||||
}
|
||||
|
||||
main>section#summary>div>span:first-of-type {
|
||||
/* margin-left: auto; */
|
||||
}
|
||||
|
@ -27,6 +91,19 @@ main>section#summary>div>button#order {
|
|||
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 {
|
||||
position: relative;
|
||||
width: 100%;
|
||||
|
@ -137,3 +214,9 @@ main>section#products>article.product>div>div.footer>input {
|
|||
padding: 0 0.3rem;
|
||||
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);
|
||||
}
|
||||
|
||||
.rounded {
|
||||
border-radius: 0.75rem;
|
||||
}
|
||||
|
||||
.row {
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
}
|
||||
|
||||
.column {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
}
|
||||
|
||||
.unselectable {
|
||||
-webkit-touch-callout: none;
|
||||
-webkit-user-select: none;
|
||||
|
|
|
@ -16,9 +16,7 @@ header>nav#menu {
|
|||
header>nav#menu>a[type="button"] {
|
||||
height: 3rem;
|
||||
padding: unset;
|
||||
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)); */
|
||||
border-radius: 1.375rem;
|
||||
color: var(--tg-theme-button-text-color);
|
||||
background-color: var(--tg-theme-button-color);
|
||||
}
|
||||
|
@ -32,25 +30,25 @@ header>nav#menu>a[type="button"]>* {
|
|||
}
|
||||
|
||||
@container header (max-width: 450px) {
|
||||
header>nav#menu > a[type="button"]:nth-child(1)> i.icon+span {
|
||||
header>nav#menu>a[type="button"]:nth-child(1)>i.icon+span {
|
||||
display: none;
|
||||
}
|
||||
}
|
||||
|
||||
@container header (max-width: 350px) {
|
||||
header>nav#menu > a[type="button"]:nth-child(2)> i.icon+span {
|
||||
header>nav#menu>a[type="button"]:nth-child(2)>i.icon+span {
|
||||
display: none;
|
||||
}
|
||||
}
|
||||
|
||||
@container header (max-width: 250px) {
|
||||
header>nav#menu > a[type="button"]:nth-child(3)> i.icon+span {
|
||||
header>nav#menu>a[type="button"]:nth-child(3)>i.icon+span {
|
||||
display: none;
|
||||
}
|
||||
}
|
||||
|
||||
@container header (max-width: 150px) {
|
||||
header>nav#menu > a[type="button"]> i.icon+span {
|
||||
header>nav#menu>a[type="button"]>i.icon+span {
|
||||
display: none;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -133,15 +133,17 @@ section#window>div.card>p:last-of-type {
|
|||
}
|
||||
|
||||
section#window>div.card>div.footer {
|
||||
container-type: inline-size;
|
||||
container-name: window-footer;
|
||||
padding: 0.8rem 2.3rem;
|
||||
display: flex;
|
||||
flex-flow: row wrap;
|
||||
align-items: baseline;
|
||||
gap: 0 0.8rem;
|
||||
gap: 0.8rem;
|
||||
background-color: var(--tg-theme-header-bg-color);
|
||||
}
|
||||
|
||||
section#window>div.card>div.footer>small.dimensions {
|
||||
margin-left: 1.5rem;
|
||||
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 {
|
||||
margin-left: auto;
|
||||
margin-right: 1.5rem;
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
|
@ -159,3 +160,20 @@ section#window>div.card>div.footer>button.buy {
|
|||
width: 100%;
|
||||
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,
|
||||
mirzaev\arming_bot\models\account,
|
||||
mirzaev\arming_bot\models\settings,
|
||||
mirzaev\arming_bot\models\cart,
|
||||
mirzaev\arming_bot\models\enumerations\language,
|
||||
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 account|null $account The object implementing an account 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
|
||||
*/
|
||||
|
@ -58,7 +56,6 @@ final class templater extends controller implements ArrayAccess
|
|||
?session $session = null,
|
||||
?account $account = null,
|
||||
?settings $settings = null,
|
||||
?cart $cart = null
|
||||
) {
|
||||
// Initializing an instance of twig
|
||||
$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);
|
||||
$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('cart', ['summary' => $cart->summary(currency: $currency), 'products' => $cart->products(language: $language, currency: $currency)]);
|
||||
|
||||
// @todo move functions into controllers
|
||||
|
||||
// Initialize function of dimensions formatting
|
||||
$this->twig->addFunction(
|
||||
|
|
|
@ -6,7 +6,7 @@
|
|||
{% if account is empty %}
|
||||
<section id="account">
|
||||
<a onclick="core.account.authentication()">
|
||||
<!-- {{ language == 'ru' ? "Аутентификация" : "Authentication" }} -->
|
||||
{{ language == 'ru' ? "Аутентификация" : "Authentication" }}
|
||||
</a>
|
||||
</section>
|
||||
{% else %}
|
||||
|
@ -19,5 +19,5 @@
|
|||
{% endblock %}
|
||||
|
||||
{% block js %}
|
||||
<script src="/js/account.js"></script>
|
||||
<script src="/js/modules/account.js" type="module"></script>
|
||||
{% 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) %}
|
||||
<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 %}>
|
||||
<a data-product="cover" href="?product={{ product.identifier }}" onclick="return core.catalog.product(this);"
|
||||
onkeydown="event.keyCode === 13 && core.catalog.product(this)" tabindex="10">
|
||||
|
@ -40,8 +40,9 @@
|
|||
</article>
|
||||
{% endmacro %}
|
||||
{% if cart.products is not empty %}
|
||||
<section id="products" class="unselectable">
|
||||
<section id="products" class="column unselectable">
|
||||
{% for product in cart.products %}
|
||||
{{ product.summary }}
|
||||
{{ _self.card(product.document, product.amount) }}
|
||||
{% endfor %}
|
||||
</section>
|
||||
|
|
|
@ -1,10 +1,13 @@
|
|||
{% if cart.products is not empty %}
|
||||
<section id="summary" class="unselectable">
|
||||
<div>
|
||||
<section id="summary"
|
||||
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>{{ 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)"
|
||||
<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>
|
||||
</div>
|
||||
</section>
|
||||
|
|
|
@ -12,13 +12,15 @@
|
|||
{% endblock %}
|
||||
|
||||
{% 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/products.html" %}
|
||||
{% endblock %}
|
||||
|
||||
{% block js %}
|
||||
{{ parent() }}
|
||||
<script src="/js/cart.js"></script>
|
||||
<script src="/js/hotline.js"></script>
|
||||
<script src="/js/modules/delivery.js" type="module"></script>
|
||||
<script src="/js/modules/cart.js" type="module"></script>
|
||||
<script src="/js/modules/hotline.js" type="module"></script>
|
||||
{% endblock %}
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
{% if filters is not empty %}
|
||||
<section id="filters" class="unselectble">
|
||||
<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 %}>
|
||||
<label for="brand_title" type="button" onclick="core.catalog.parameters.set('brand', null); core.catalog.search(event)">
|
||||
{{ 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">
|
||||
<span data-product-parameter="amount">{{ amount }}</span>
|
||||
<span class="cost currency" data-product-parameter="cost">{{ product.cost }}</span>
|
||||
<span data-product-parameter="currency">{{ currency.symbol }}</span>
|
||||
</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>
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
<search id="search">
|
||||
<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"
|
||||
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 %} />
|
||||
|
|
|
@ -12,7 +12,7 @@
|
|||
{% endblock %}
|
||||
|
||||
{% 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/categories.html" %}
|
||||
{% include "/themes/default/catalog/elements/filters.html" %}
|
||||
|
@ -21,7 +21,7 @@
|
|||
|
||||
{% block js %}
|
||||
{{ parent() }}
|
||||
<script src="/js/catalog.js"></script>
|
||||
<script src="/js/cart.js"></script>
|
||||
<script src="/js/hotline.js"></script>
|
||||
<script src="/js/modules/catalog.js" type="module"></script>
|
||||
<script src="/js/modules/cart.js" type="module"></script>
|
||||
<script src="/js/hotline.js" type="module"></script>
|
||||
{% endblock %}
|
||||
|
|
|
@ -10,5 +10,5 @@
|
|||
{% endblock %}
|
||||
|
||||
{% block js %}
|
||||
<script src="/js/connection.js"></script>
|
||||
<script src="/js/modules/connection.js" type="module"></script>
|
||||
{% endblock %}
|
||||
|
|
|
@ -1,38 +1,20 @@
|
|||
{% block js %}
|
||||
<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/damper.js"></script>
|
||||
<script src="/js/loader.js"></script>
|
||||
<script src="/js/telegram.js"></script>
|
||||
<script src="/js/session.js"></script>
|
||||
<script src="/js/modules/loader.js" type="module"></script>
|
||||
<script src="/js/modules/telegram.js" type="module"></script>
|
||||
<script src="/js/modules/session.js" type="module"></script>
|
||||
<script src="/js/authentication.js"></script>
|
||||
{% if javascript is not empty %}
|
||||
<script>
|
||||
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);
|
||||
core.modules.connect("damper").then(() => {
|
||||
let _window;
|
||||
|
||||
function initialization() {
|
||||
let _window;
|
||||
{% for code in javascript %}
|
||||
{{ code|raw }}
|
||||
{% endfor %}
|
||||
}
|
||||
})
|
||||
);
|
||||
{% for code in javascript %}
|
||||
{{ code|raw }}
|
||||
{% endfor %}
|
||||
});
|
||||
</script>
|
||||
{% endif %}
|
||||
{% endblock %}
|
||||
|
|
|
@ -12,7 +12,7 @@
|
|||
{% for button in menu %}
|
||||
<a href='{{ button.urn }}' onclick="return core.loader.load('{{ button.urn }}');" type="button" class="unselectable"
|
||||
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 %}
|
||||
<i class="icon {{ button.icon.class }}" {% if button.icon.style %}
|
||||
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