From 99daad5074dc03b54a957fb940f69491a765242b Mon Sep 17 00:00:00 2001 From: Arsen Mirzaev Tatyano-Muradovich Date: Fri, 29 May 2026 10:34:16 +0000 Subject: [PATCH] PRINT TO A6 PAPER --- composer.json | 12 +- damper.mjs | 2 +- install.sh | 21 ++ pechatalka.mjs | 2 +- .../system/controllers/generator.php | 129 ++++++++++-- .../pechatalka/system/controllers/index.php | 2 +- .../pechatalka/system/databases/.gitignore | 0 .../models/enumerations/products/type.php | 22 ++- svoboda/pechatalka/system/models/paper.php | 158 +++++++++++++++ svoboda/pechatalka/system/models/product.php | 132 +++++++++++++ svoboda/pechatalka/system/public/index.php | 2 +- svoboda/pechatalka/system/public/js/core.js | 183 +++++++++++++++--- .../system/public/js/modules/damper.mjs | 2 +- .../system/public/js/modules/generator.mjs | 45 +++-- .../system/public/js/modules/pechatalka.mjs | 2 +- .../system/public/js/pages/generator/pin.js | 10 +- .../default/css/pages/generator/pin.css | 20 +- .../system/storage/products/.gitignore | 2 + .../generator/pin/elements/pechatalka.html | 26 +-- .../default/generator/pin/elements/title.html | 4 +- .../system/views/themes/default/js.html | 16 -- 21 files changed, 672 insertions(+), 120 deletions(-) mode change 100644 => 100755 svoboda/pechatalka/system/databases/.gitignore create mode 100644 svoboda/pechatalka/system/models/paper.php create mode 100644 svoboda/pechatalka/system/models/product.php create mode 100644 svoboda/pechatalka/system/storage/products/.gitignore diff --git a/composer.json b/composer.json index 0a15589..75a23b0 100755 --- a/composer.json +++ b/composer.json @@ -15,7 +15,7 @@ "name": "Arsen Mirzaev Tatyano-Muradovich", "email": "arsen@mirzaev.sexy", "homepage": "https://mirzaev.sexy", - "role": "Creator" + "role": "Developer" } ], "support": { @@ -23,9 +23,10 @@ "issues": "https://git.svoboda.works/svoboda/pechatalka/issues" }, "require": { - "php": "^8.4", - "mirzaev/minimal": "^3", - "mirzaev/baza": "^3.3", + "php": "^8.5", + "ext-imagick": "^3.8", + "mirzaev/minimal": "^3.10", + "mirzaev/baza": "^3.4.3", "twig/twig": "^3.2", "twig/extra-bundle": "^3.7", "twig/intl-extra": "^3.10", @@ -33,7 +34,8 @@ "imagine/imagine": "^1.5", "badfarm/zanzara": "^0.9.1", "nyholm/psr7": "^1.8", - "react/filesystem": "^0.1.2" + "react/filesystem": "^0.1.2", + "mirzaev/record": "^2.2" }, "autoload": { "psr-4": { diff --git a/damper.mjs b/damper.mjs index 68589e9..81d208b 160000 --- a/damper.mjs +++ b/damper.mjs @@ -1 +1 @@ -Subproject commit 68589e968cbc043f35c2948a9c90293b6f5f9cb9 +Subproject commit 81d208b96470e6068e735f38ccfc0f941079c3a5 diff --git a/install.sh b/install.sh index d055c6f..f582c33 100755 --- a/install.sh +++ b/install.sh @@ -1,5 +1,7 @@ #!/bin/bash +git submodule update --init --recursive + if [ -d author/project ]; then mv author/project author/pechatalka fi @@ -8,3 +10,22 @@ if [ -d author ]; then mv author mirzaev fi +for i in svoboda/pechatalka/system/settings/*.sample; do + echo $i; + if [ ! -f "${i/.sample/}" ]; then + cp -n "$i" "${i/.sample/}"; + echo ${i/.sample/}; + fi +done + +if ! [ -d svoboda/pechatalka/system/public/js/modules ]; then + mkdir svoboda/pechatalka/system/public/js/modules -p +fi + +if ! [ -L svoboda/pechatalka/system/public/js/modules/damper.mjs ]; then + ln -s ../../../../../../damper.mjs/damper.mjs svoboda/pechatalka/system/public/js/modules/damper.mjs; +fi + +if ! [ -L svoboda/pechatalka/system/public/js/modules/pechatalka.mjs ]; then + ln -s ../../../../../../pechatalka.mjs/pechatalka.mjs svoboda/pechatalka/system/public/js/modules/pechatalka.mjs; +fi diff --git a/pechatalka.mjs b/pechatalka.mjs index b140047..c94542b 160000 --- a/pechatalka.mjs +++ b/pechatalka.mjs @@ -1 +1 @@ -Subproject commit b1400479c4f06b49d0a6d6d5c4496cd9b4430752 +Subproject commit c94542bfd3c843d06f3a24611c07da12cc5ae14e diff --git a/svoboda/pechatalka/system/controllers/generator.php b/svoboda/pechatalka/system/controllers/generator.php index 567502f..bc042b3 100755 --- a/svoboda/pechatalka/system/controllers/generator.php +++ b/svoboda/pechatalka/system/controllers/generator.php @@ -6,7 +6,9 @@ namespace svoboda\pechatalka\controllers; // Files of the project use svoboda\pechatalka\controllers\core, - svoboda\pechatalka\models\enumerations\products\type; + svoboda\pechatalka\models\paper, + svoboda\pechatalka\models\product, + svoboda\pechatalka\models\enumerations\products\type as product_type; // Framework for PHP use mirzaev\minimal\http\enumerations\content, @@ -72,42 +74,127 @@ final class generator extends core /** * Print * - * Assemble and generate the blank from layers and prepare to printing + * Assemble and generate the blank from products and prepare to printing * * @return null */ public function print( - string $type, - string|int $amount = 1, - ?string $display + string $type = '', + string $products = '', + ?string $canvas = null ): null { // Type - $type = type::{$type} ?? null; + !empty($type) and $type = product_type::{$type} ?? null; // Amount - preg_match('/[\d]+/', (string) $amount, $matches); + /* preg_match('/[\d]+/', (string) $amount, $matches); $amount = (int) $matches[0] ?? 1; - unset($matches); + unset($matches); */ - // Display - $display = json_decode($display, true, 10); + // Initializing products data + $products = json_decode($products, true, 16); - if ($type instanceof type && $amount > 0) { + // Initializing the canvas data + $canvas = json_decode($canvas, true, 16); + + if ($type instanceof product_type && count($products) > 0) { // Initialized all required arguments - // Universalizing received images - $files_images = array_filter($this->request->files, fn(string $key) => preg_match('/^layer_\d{1,2}_image/', $key), ARRAY_FILTER_USE_KEY); + // Declaring the images buffer + $images = []; - // Initializing the combined images buffer - $images_combined = []; + foreach ($this->request->files as $name => $file) { + // Iterating over received files - for ($i = 0; $i < count($files_images); ++$i) { - // Iterating over images + // Deserializing the file type + !empty($file['type']) && is_string($file['type']) and $file['type'] = content::from($file['type']) ?? null; - // Combining images with sorting - if (empty($display[$i]['image'])) $images_combined[] = $display[$i]['image']; - if (!empty($files_images["image_$i"])) $images_combined[] = $files_images["image_$i"]; - if (empty($display[$i]['image'])) $display[$i]['image'] = $files_images[$i]; + if (match ($file['type']) { + content::jpeg, + content::png, + content::webp => true, + default => false + }) { + // Passed the file type filter + + // Writing into the images buffer + $images[$name] = $file; + } + } + + foreach ($products as $product => &$layers) { + // Iterating over products + + // Creating the product + $instance = new product()->create( + account: 0, + type: $type, + layers: $layers, + canvas: $canvas + ); + + // Initializing the product storage path + $storage = STORAGE + . DIRECTORY_SEPARATOR + . 'products' + . DIRECTORY_SEPARATOR + . $instance->identifier; + + if (!file_exists(filename: $storage)) { + // The product storage directory is not created + + if (mkdir(directory: $storage, permissions: 0755, recursive: true)) { + // Created the product storage directory + } else { + // Nor created the product storage directory + + // Exit (fail) + return null; + } + } + + foreach (array_filter($images, fn(string $key) => preg_match('/^' . $product . '_\d{1,2}$/', $key), ARRAY_FILTER_USE_KEY) as $name => $image) { + // Iterating over the product images + + // Initializing the layer + preg_match('/\d{1,2}$/', $name, $matches); + $layer = $matches[0]; + + if (!empty($layer) || $layer == 0) { + // Initialized the layer + + // Initializing the product layer image file path + $path = $storage . DIRECTORY_SEPARATOR . $layer . '.' . $image['type']->extension(); + + if (copy(from: $image['tmp_name'], to: $path)) { + // Copied the product layer image into the product storage + + // Matching the product image with the product + $layers[$layer]['image'] = $path; + } + } + } + } + + foreach ($products as $product) { + // Iterating over products + + foreach ($product as $layer) { + // Iterating over the product layer + + if (empty($layer['image'])) { + // Found the empty layer + + // Exit (fail) + return null; + } + } + } + + if ($type === product_type::pin_37) { + // Pin 37mm + + $biba = paper::a5(type: $type, products: $products, canvas: $canvas); } if (str_contains($this->request->headers['accept'], content::any->value)) { diff --git a/svoboda/pechatalka/system/controllers/index.php b/svoboda/pechatalka/system/controllers/index.php index fa50853..eefce98 100755 --- a/svoboda/pechatalka/system/controllers/index.php +++ b/svoboda/pechatalka/system/controllers/index.php @@ -41,7 +41,7 @@ final class index extends core */ public function index(): null { - if (str_contains($this->request->headers['accept'], content::any->value)) { + if (str_contains($this->request->headers['accept'] ?? '', content::any->value)) { // Request for any response // Render page diff --git a/svoboda/pechatalka/system/databases/.gitignore b/svoboda/pechatalka/system/databases/.gitignore old mode 100644 new mode 100755 diff --git a/svoboda/pechatalka/system/models/enumerations/products/type.php b/svoboda/pechatalka/system/models/enumerations/products/type.php index 7f5d7f5..d302882 100644 --- a/svoboda/pechatalka/system/models/enumerations/products/type.php +++ b/svoboda/pechatalka/system/models/enumerations/products/type.php @@ -15,5 +15,25 @@ namespace svoboda\pechatalka\models\enumerations\products; enum type { case pin_37; -} + /** + * Areas + * + * @return array ['visible' => ['width', 'height'], 'blank' => ['width', 'height']] + */ + public function areas(): array + { + return match ($this) { + type::pin_37 => [ + 'visible' => [ + 'width' => 37, + 'height' => 37 + ], + 'blank' => [ + 'width' => 48.5, + 'height' => 48.5 + ] + ] + }; + } +} diff --git a/svoboda/pechatalka/system/models/paper.php b/svoboda/pechatalka/system/models/paper.php new file mode 100644 index 0000000..36cd9f6 --- /dev/null +++ b/svoboda/pechatalka/system/models/paper.php @@ -0,0 +1,158 @@ + + */ +final class paper extends core +{ + /** + * A5 + * + * + * + * @return record The account record from the database + */ + public static function a5(product_type $type, array $products, array $canvas = []): mixed + { + // Initializing the print DPI + define('dpi', 80); + /* define('dpi', 300); */ + + // Initializing the A5 paper dimensions + $a5 = [ + 'width' => (int) round(10.5 * dpi), + 'height' => (int) round(14.8 * dpi) + ]; + + // Initializing the paper + $paper = new imagick(); + $paper->setResolution(dpi, dpi); + $paper->newImage($a5['width'], $a5['height'], new imagick_pixel("white")); + $paper->setImageUnits(imagick::RESOLUTION_PIXELSPERCENTIMETER); + $paper->setImageFormat("jpg"); + + foreach ($products as $product) { + // Iterating over products + + foreach ($product as $layer) { + // Iterating over the product layers + + // Filtering + empty($layer['scale']) || $layer['scale'] == 0 and $layer['scale'] = 1; + + // Initializing the product areas + $areas = $type->areas(); + + // Calculating the product blank dimensions by the print DPI + $blank = [ + 'width' => (int) round($areas['blank']['width'] / 10 * dpi), + 'height' => (int) round($areas['blank']['height'] / 10 * dpi) + ]; + + // Calculating the DPI ratio of the pechatalka interface to the blank dimensions + $ratio = [ + 'width' => $blank['width'] / $canvas['width'], + 'height' => $blank['height'] / $canvas['height'] + ]; + + // Initializing the circle mask + $circle = new imagick(); + $circle->setResolution(dpi, dpi); + $circle->newImage($blank['width'], $blank['height'], '#0008'); + $circle->setImageUnits(imagick::RESOLUTION_PIXELSPERCENTIMETER); + $circle->setimageformat('png'); + $circle->setimagematte(true); + $draw = new imagick_draw(); + $draw->setfillcolor('#fff'); + $draw->circle($blank['width'] / 2, $blank['height'] / 2, $blank['width'] / 2, $blank['height']); + $circle->drawimage($draw); + + // Initializing the layer image + $image = new imagick(); + $image->setResolution(dpi, dpi); + $image->readImage($layer['image']); + $image->setImageUnits(imagick::RESOLUTION_PIXELSPERCENTIMETER); + $image->setimagematte(true); + + $width = (int) round($blank['width'] * $layer['scale']); + $image->adaptiveResizeImage($width, 0); + /* $image->roundCornersImage(50, 50); */ + + $offset = [ + 'x' => ($blank['width'] - $image->getImageWidth()) / 2, + 'y' => ($blank['height'] - $image->getImageHeight()) / 2 + ]; + + $vertical = $blank['height'] - $image->getImageHeight(); + + + + // Добавить нормальные комментарии после глубокго тестирования + + + + + // Reinitializing the product layer offsets + $layer['x'] = (int) round($layer['x'] * $ratio['width']); + $layer['y'] = (int) round($layer['y'] * $ratio['height']); + + $image->compositeImage( + $circle, + imagick::COMPOSITE_DSTIN, + (int) round(-$layer['x'] - $offset['x']), + /* (int) round(-$layer['y'] - $offset['y'] - $vertical / 2) */ + (int) round(-$layer['y'] - $offset['y']) + ); + + // Compositing the layer with the paper + $paper->setImageVirtualPixelMethod(imagick::VIRTUALPIXELMETHOD_TRANSPARENT); + $paper->setImageArtifact('compose:args', "1,0,-0.5,0.5"); + $paper->compositeImage( + $image, + imagick::COMPOSITE_MATHEMATICS, + (int) round($a5['width'] / 2 - $blank['width'] / 2 + $layer['x'] + $offset['x']), + /* (int) round($a5['height'] / 2 - $blank['height'] / 2 + $layer['y'] + $offset['y'] + $vertical / 2) */ + (int) round($a5['height'] / 2 - $blank['height'] / 2 + $layer['y'] + $offset['y']) + ); + + // Writing the paper file + $paper->writeImage(INDEX . DIRECTORY_SEPARATOR . 'test.jpg'); + } + } + + return true; + } +} diff --git a/svoboda/pechatalka/system/models/product.php b/svoboda/pechatalka/system/models/product.php new file mode 100644 index 0000000..5d854eb --- /dev/null +++ b/svoboda/pechatalka/system/models/product.php @@ -0,0 +1,132 @@ + + */ +final class product extends core implements record_interface +{ + use record_trait; + + /** + * File + * + * @var string $database Path to the database file + */ + protected string $file = DATABASES . DIRECTORY_SEPARATOR . 'products.baza'; + + /** + * Database + * + * @method record|null $record The record + * + * @var database $database The database + */ + public protected(set) database $database; + + /** + * Serialized + * + * @var bool $serialized Is the implementator object serialized? + */ + private bool $serialized = true; + + /** + * Constructor + * + * @return void + */ + public function __construct(?record $record = null) + { + // Initializing the database + $this->database = new database() + ->encoding(encoding::utf8) + ->columns( + new column('identifier', type::integer_unsigned), + new column('account', type::integer_unsigned), + new column('type', type::string, ['length' => 32]), + new column('layers', type::string, ['length' => 4096]), + new column('canvas', type::string, ['length' => 4096]), + new column('updated', type::integer_unsigned), + new column('created', type::integer_unsigned) + ) + ->connect($this->file); + + // Initializing the record + $record instanceof record and $this->record = $record; + + } + + /** + * Create + * + * @param int $account The account identifier + * @param string|product_type $type The product type + * @param string|array $layers The product layers (JSON) + * @param string|array $canvas The product canvas (JSON) + * + * @return int|false The instance, if created + */ + public function create( + int $account, + string|product_type $type, + string|array $layers, + string|array|null $canvas = null + ): static|false + { + // Initializing the identifier + $identifier = $this->database->count() + 1; + + // Initializing the record + $record = $this->database->record( + $identifier, + $account, + $type instanceof product_type ? $type->name : $type, + is_string($layers) && json_validate($layers, depth: 16) ? $layers : json_encode($layers, depth: 16), + is_string($canvas) && json_validate($canvas, depth: 16) ? $canvas : json_encode($canvas, depth: 16), + svoboda::timestamp(), + svoboda::timestamp() + ); + + // Writing the record into the database + $created = $this->database->write($record); + + // Exit (success) + return $record ? new static(record: $record) : false; + } +} + diff --git a/svoboda/pechatalka/system/public/index.php b/svoboda/pechatalka/system/public/index.php index 66c590c..f9524e2 100755 --- a/svoboda/pechatalka/system/public/index.php +++ b/svoboda/pechatalka/system/public/index.php @@ -50,7 +50,7 @@ $core = new core(namespace: __NAMESPACE__); // Initializing routes $core->router ->write('/', new route('index', 'index'), 'GET') - ->write('/generator/print', new route('generator', 'print'), 'POST') + ->write('/generator/print', new route('generator', 'print', options: ['controller_method_arguments' => 'strict']), 'POST') ->write('/generator/pin', new route('generator', 'pin'), 'GET') ; diff --git a/svoboda/pechatalka/system/public/js/core.js b/svoboda/pechatalka/system/public/js/core.js index 269b08f..42ad505 100644 --- a/svoboda/pechatalka/system/public/js/core.js +++ b/svoboda/pechatalka/system/public/js/core.js @@ -10,17 +10,25 @@ * @author Arsen Mirzaev Tatyano-Muradovich */ class core { + /** + * @name Global modules + * + * @type {object} + */ + static global = {}; + + /** + * @name System modules + * + * @type {object} + */ + static system = {}; + // Domain static domain = window.location.hostname; // Language - static language = "english"; - - // Currency - static currency = { name: "usd", symbol: "$" }; - - // Theme - static theme = window.getComputedStyle(document.getElementById("theme")); + static language = "ru"; // Window static window; @@ -81,6 +89,42 @@ class core { ); } + /** + * @name Buffer + */ + static buffer = class buffer { + /** + * @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 {bool} Execution completed with an error? + */ + static write(name, value) { + core.modules.connect("damper").then( + () => { + // Imported the damper module + + // Execute under damper + this.write.damper(name, value); + }, + () => { + // Not imported the damper module + + // Execute + this.write.system(name, value); + }, + ); + + // Exit (success) + return false; + } + }; + /** * Сгенерировать окно выбора действия * @@ -95,7 +139,7 @@ class core { * * @return {void} */ - /* static choose = core.damper( + /* static choose = core.global.damper( ( title = "Выбор действия", text = "", @@ -269,32 +313,125 @@ Object.assign( /** * @name Connect modules * - * @param {Array|string} modules Names of modules or name of the module + * @param {(Array|string)} global Names of global modules without extension (`.mjs` only) + * @param {(Array|string)} system Names of system modules without extenstion (`.mjs` only) * - * @return {Prommise} + * @return {Promise} */ - async connect(modules) { - // Normalisation required argiments - if (typeof modules === "string") modules = [modules]; + async connect(global, system) { + // Normalisation required arguments + if (typeof global === "string") global = [global]; + if (typeof system === "string") system = [system]; - if (modules instanceof Array) { - // Received and validated required arguments + // Initializing the registry of connected modules + const connected = { + system: [], + global: [] + }; - // Initializing the registry of loaded modules - const loaded = []; + if (global?.length > 0) { + // Global - for (const module of modules) { - // Iterating over modules + for (const module of global) { + // Iterating over global modules - // Downloading, importing and writing the module into a core property and into registry of loaded modules - core[module] = - loaded[module] = + // Downloading, importing and writing the global module into a core property and into registry of connected modules + core.global[module] = + connected.global[module] = await (await import(`./modules/${module}.mjs`)).default; } + } + + if (system?.length > 0) { + // System + + for (const module of system) { + // Iterating over system modules + + // Downloading, importing and writing the system module into a core property and into registry of connected modules + core.system[module] = + connected.system[module] = + await (await import(`./modules/system/${module}.mjs`)).default; + } + } + + // Exit (success) + return connected; + }, + }, +); + +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.global.damper( + (...variables) => core.buffer.write.system(...variables), + 300, + 2, + ), + }, + ); +}); + +/** + * @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 + core.session.buffer?.write(name, value); + }); + + core.modules.connect("account").then(() => { + // Imported the account module + + // Write to the account buffer + core.account.buffer?.write(name, value); + }); // Exit (success) - return loaded; + resolve(); + } catch (e) { + // Exit (fail) + reject(e); } }, }, ); + +// Dispatching event: "core.initialized" +document.dispatchEvent(new CustomEvent("core.initialized")); diff --git a/svoboda/pechatalka/system/public/js/modules/damper.mjs b/svoboda/pechatalka/system/public/js/modules/damper.mjs index 881957a..2b4d1e5 120000 --- a/svoboda/pechatalka/system/public/js/modules/damper.mjs +++ b/svoboda/pechatalka/system/public/js/modules/damper.mjs @@ -1 +1 @@ -../../../../../../damper.mjs/damper.min.mjs \ No newline at end of file +../../../../../../damper.mjs/damper.mjs \ No newline at end of file diff --git a/svoboda/pechatalka/system/public/js/modules/generator.mjs b/svoboda/pechatalka/system/public/js/modules/generator.mjs index 8461433..73f3aa1 100644 --- a/svoboda/pechatalka/system/public/js/modules/generator.mjs +++ b/svoboda/pechatalka/system/public/js/modules/generator.mjs @@ -66,7 +66,7 @@ core.modules.connect("damper").then(() => { * * @return {void} */ - damper: core.damper( + damper: core.global.damper( (...variables) => generator.print.system(...variables), 300, 4, @@ -117,10 +117,25 @@ Object.assign( // Writing parameters into the body buffer body.append("type", type); - body.append("amount", amount); - // Initializing the display JSON buffer - const display = {}; + // Initializing the canvas JSON buffer + /* const canvas = { + width: + }; + */ + // const background = ; + + // Writing canvas into the body buffer + body.append("canvas", JSON.stringify({ + width: canvas.clientWidth, + height: canvas.clientHeight + })); + + // + // Iterating over products + + // Initializing the product JSON buffer + const product = {}; for (const layer of canvas.querySelectorAll("div.layer")) { // Iterating over layers @@ -134,15 +149,14 @@ Object.assign( // Initialized the layer index // Initializing the layer - display[index] ??= {}; + product[index] ??= {}; // Writing the layer parameters - display[index].x = + product[index].x = parseInt(layer.style.getPropertyValue("left")) || 0; - display[index].y = + product[index].y = parseInt(layer.style.getPropertyValue("top")) || 0; - display[index].scale = - (parseInt(layer.style.getPropertyValue("scale")) || 1) * 100; + product[index].scale = parseFloat(layer.style.getPropertyValue("scale") || 1); // Initializing the layer type const type = layer.getAttribute("data-layer-type"); @@ -168,14 +182,14 @@ Object.assign( await fetch(src).then((r) => r.blob()).then((value) => { // Converted "blob:..." string to the Blob object - // Writing into the body buffer - body.append("layer_" + index + "_image", value, index); + // Writing into the body buffer (`{$product}_{$layer}`) + body.append("0_" + index, value, index); }); } else { // URL (expected) // Writing the layer parameter - display[index].image = src; + product[index].image = src; } } } @@ -185,8 +199,8 @@ Object.assign( } } - // Writing into the body buffer - body.append("display", JSON.stringify(display)); + // Writing products into the body buffer (the only one canvas) + body.append("products", JSON.stringify({0: product})); return await core.request( "/generator/print", @@ -226,6 +240,3 @@ Object.assign( }, }, ); - -// Connecting to the core -if (!core.generator) core.generator = generator; diff --git a/svoboda/pechatalka/system/public/js/modules/pechatalka.mjs b/svoboda/pechatalka/system/public/js/modules/pechatalka.mjs index 39d79f6..a07d364 120000 --- a/svoboda/pechatalka/system/public/js/modules/pechatalka.mjs +++ b/svoboda/pechatalka/system/public/js/modules/pechatalka.mjs @@ -1 +1 @@ -../../../../../../pechatalka.mjs/pechatalka.min.mjs \ No newline at end of file +../../../../../../pechatalka.mjs/pechatalka.mjs \ No newline at end of file diff --git a/svoboda/pechatalka/system/public/js/pages/generator/pin.js b/svoboda/pechatalka/system/public/js/pages/generator/pin.js index fcae9a2..7b85853 100644 --- a/svoboda/pechatalka/system/public/js/pages/generator/pin.js +++ b/svoboda/pechatalka/system/public/js/pages/generator/pin.js @@ -1,9 +1,9 @@ -core.modules.connect(["pechatalka"]) +core.modules.connect(["generator", "pechatalka"]) .then(() => { - // Imported the pechatalka module + // Imported modules // Initializing the instance - const instance = new core.pechatalka( + const instance = core.global.pechatalka = new core.global.pechatalka( document.getElementById("pechatalka"), document.getElementById("pechatalka")?.querySelector(".canvas"), document.getElementById("pechatalka")?.querySelector(".result"), @@ -11,12 +11,8 @@ core.modules.connect(["pechatalka"]) ["interface", true], ["round", true], ]), - true, ); - // Reinitializing the core instance of pechatalka - core.pechatalka = instance; - // instence.layers.set('interface', true) // Reinitializing the `layer create` event diff --git a/svoboda/pechatalka/system/public/themes/default/css/pages/generator/pin.css b/svoboda/pechatalka/system/public/themes/default/css/pages/generator/pin.css index d01066e..f33fd23 100644 --- a/svoboda/pechatalka/system/public/themes/default/css/pages/generator/pin.css +++ b/svoboda/pechatalka/system/public/themes/default/css/pages/generator/pin.css @@ -1,6 +1,6 @@ @charset "UTF-8"; -section#title { +div#title { position: relative; height: 100px; display: flex; @@ -23,7 +23,7 @@ section#title { } } -section#pechatalka { +div#pechatalka { --width: 300px; width: var(--width, 300px); flex-grow: 1; @@ -33,7 +33,7 @@ section#pechatalka { align-items: center; gap: 2rem; - >section.system { + >div.system { display: none; } @@ -86,7 +86,7 @@ section#pechatalka { } } - >section.canvas.pin { + >div.canvas.pin { --diameter-cut: 250px; --offset: calc(37 / 48 * 100); --diameter-display: calc(var(--diameter-cut) * var(--offset) / 100); @@ -150,10 +150,12 @@ section#pechatalka { >div.layer { z-index: 100; position: absolute; - min-width: 50%; - max-width: 200%; + /* min-width: 50%; + max-width: 200%; */ width: calc(var(--diameter-cut, var(--width, 100%)) + var(--width-zoom, 0px)); + height: calc(var(--diameter-cut, var(--width, 100%)) + var(--width-zoom, 0px)); cursor: grab; + align-content: center; &:active { cursor: grabbing; @@ -195,8 +197,8 @@ section#pechatalka { } } - &:has(> section.canvas.pin > div.layer) { - >section.result { + &:has(> div.canvas.pin > div.layer) { + >div.result { >button.buy { cursor: pointer !important; filter: unset; @@ -204,7 +206,7 @@ section#pechatalka { } } - >section.result { + >div.result { /* margin-top: auto; */ margin-bottom: 1rem; width: 100%; diff --git a/svoboda/pechatalka/system/storage/products/.gitignore b/svoboda/pechatalka/system/storage/products/.gitignore new file mode 100644 index 0000000..d6b7ef3 --- /dev/null +++ b/svoboda/pechatalka/system/storage/products/.gitignore @@ -0,0 +1,2 @@ +* +!.gitignore diff --git a/svoboda/pechatalka/system/views/themes/default/generator/pin/elements/pechatalka.html b/svoboda/pechatalka/system/views/themes/default/generator/pin/elements/pechatalka.html index b737861..1236be4 100644 --- a/svoboda/pechatalka/system/views/themes/default/generator/pin/elements/pechatalka.html +++ b/svoboda/pechatalka/system/views/themes/default/generator/pin/elements/pechatalka.html @@ -1,29 +1,29 @@ -
-
+
+
+ multiple="false" onchange="core.global.pechatalka.image(this.files[0], 160);" /> -
+ oninput="core.global.pechatalka?.wrap?.querySelector('label[for=\'pechatalka_background\']>div.color')?.style.setProperty('--color', event.target.value); core.global.pechatalka.canvas.style.setProperty('background-color', event.target.value);" /> + -
+
-
+ -
+
0 -
-
+ + diff --git a/svoboda/pechatalka/system/views/themes/default/generator/pin/elements/title.html b/svoboda/pechatalka/system/views/themes/default/generator/pin/elements/title.html index cf43563..f68d735 100644 --- a/svoboda/pechatalka/system/views/themes/default/generator/pin/elements/title.html +++ b/svoboda/pechatalka/system/views/themes/default/generator/pin/elements/title.html @@ -1,4 +1,4 @@ -
+

{{ language.name == 'ru' ? 'Печаталка' : 'Pechatalka' }}

{{ language.name == 'ru' ? 'Рабочий Союз Свободы' : 'Svoboda Work Union' }} -
+ diff --git a/svoboda/pechatalka/system/views/themes/default/js.html b/svoboda/pechatalka/system/views/themes/default/js.html index 82a303b..5f829e3 100755 --- a/svoboda/pechatalka/system/views/themes/default/js.html +++ b/svoboda/pechatalka/system/views/themes/default/js.html @@ -1,26 +1,10 @@ {% block js %} - {% for element in js %} - - {% endfor %} - - {% if javascript is not empty %} - - {% endif %} -