working
This commit is contained in:
parent
28f1b5e36a
commit
059c62459e
@ -1,8 +0,0 @@
|
|||||||
PSC\System\PluginBundle\Document\Plugin:
|
|
||||||
plugin_1:
|
|
||||||
name: XML Kalkulations Produkt
|
|
||||||
namespace: \Plugin\System\PSC\XmlCalc\Plugin
|
|
||||||
path: System/PSC/XmlCalc
|
|
||||||
pluginId: 19ff3fd21de9dbd7452fd0a67c928758
|
|
||||||
type: 0
|
|
||||||
installed: true
|
|
||||||
@ -1,26 +1,10 @@
|
|||||||
<?php
|
<?php
|
||||||
|
|
||||||
/**
|
|
||||||
* PrintshopCreator Suite
|
|
||||||
*
|
|
||||||
* PHP Version 5.3
|
|
||||||
*
|
|
||||||
* @author Thomas Peterson <info@thomas-peterson.de>
|
|
||||||
* @copyright 2012-2013 PrintshopCreator GmbH
|
|
||||||
* @license Private
|
|
||||||
* @link http://www.printshopcreator.de
|
|
||||||
*/
|
|
||||||
|
|
||||||
namespace PSC\Shop\MediaBundle\Document;
|
namespace PSC\Shop\MediaBundle\Document;
|
||||||
|
|
||||||
|
use Doctrine\ODM\MongoDB\Mapping\Annotations\Document;
|
||||||
use Doctrine\ODM\MongoDB\Mapping\Annotations\Field;
|
use Doctrine\ODM\MongoDB\Mapping\Annotations\Field;
|
||||||
use Doctrine\ODM\MongoDB\Mapping\Annotations\Id;
|
use Doctrine\ODM\MongoDB\Mapping\Annotations\Id;
|
||||||
use Doctrine\ODM\MongoDB\Mapping\Annotations\Document;
|
|
||||||
use Doctrine\ODM\MongoDB\Mapping\Annotations\EmbeddedDocument;
|
|
||||||
use Doctrine\ODM\MongoDB\Mapping\Annotations\EmbedOne;
|
|
||||||
use Doctrine\ODM\MongoDB\Mapping\Annotations\Index;
|
|
||||||
use Doctrine\ODM\MongoDB\Mapping\Annotations\ReferenceMany;
|
|
||||||
use Doctrine\ODM\MongoDB\Mapping\Annotations\ReferenceOne;
|
|
||||||
|
|
||||||
#[Document(collection: 'Media_Folder')]
|
#[Document(collection: 'Media_Folder')]
|
||||||
class Folder
|
class Folder
|
||||||
@ -54,6 +38,7 @@ class Folder
|
|||||||
private $subFolders = [];
|
private $subFolders = [];
|
||||||
|
|
||||||
private $media = 0;
|
private $media = 0;
|
||||||
|
|
||||||
public function __construct()
|
public function __construct()
|
||||||
{
|
{
|
||||||
$this->created = new \DateTime();
|
$this->created = new \DateTime();
|
||||||
|
|||||||
@ -13,17 +13,28 @@ class Help
|
|||||||
$this->mongoManager = $mongoManager;
|
$this->mongoManager = $mongoManager;
|
||||||
}
|
}
|
||||||
|
|
||||||
public function getHelp(string $id, string $name): ?\PSC\System\SettingsBundle\Model\Help
|
public function getHelp(null|string $id, string $name): null|\PSC\System\SettingsBundle\Model\Help
|
||||||
{
|
{
|
||||||
/** @var \PSC\System\SettingsBundle\Document\Help $doc */
|
/** @var \PSC\System\SettingsBundle\Document\Help $doc */
|
||||||
$doc = $this->mongoManager->getRepository(\PSC\System\SettingsBundle\Document\Help::class)->findOneBy(['name' => sprintf("%s_%s", $id, $name)]);
|
$doc = null;
|
||||||
|
if ($id !== null) {
|
||||||
|
$doc = $this->mongoManager
|
||||||
|
->getRepository(\PSC\System\SettingsBundle\Document\Help::class)
|
||||||
|
->findOneBy(['name' => sprintf('%s_%s', $id, $name)]);
|
||||||
|
}
|
||||||
if (null === $doc) {
|
if (null === $doc) {
|
||||||
$doc = $this->mongoManager->getRepository(\PSC\System\SettingsBundle\Document\Help::class)->findOneBy(['name' => $name]);
|
$doc = $this->mongoManager
|
||||||
|
->getRepository(\PSC\System\SettingsBundle\Document\Help::class)
|
||||||
|
->findOneBy(['name' => $name]);
|
||||||
if ($doc === null) {
|
if ($doc === null) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return new \PSC\System\SettingsBundle\Model\Help($doc->id, $doc->name, (string)$doc->helpText, (string)$doc->helpTitle);
|
return new \PSC\System\SettingsBundle\Model\Help(
|
||||||
|
$doc->id,
|
||||||
|
$doc->name,
|
||||||
|
(string) $doc->helpText,
|
||||||
|
(string) $doc->helpTitle,
|
||||||
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -0,0 +1,62 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace Plugins\Custom\PSC\FormBuilder\Api;
|
||||||
|
|
||||||
|
use Faker\Factory;
|
||||||
|
use Faker\Generator;
|
||||||
|
use PSC\Shop\ContactBundle\Repository\ContactRepository;
|
||||||
|
use Symfony\Bundle\FrameworkBundle\Test\WebTestCase;
|
||||||
|
use Tests\RefreshDatabaseTrait;
|
||||||
|
|
||||||
|
class LayoutTest extends WebTestCase
|
||||||
|
{
|
||||||
|
use RefreshDatabaseTrait;
|
||||||
|
|
||||||
|
private Generator $faker;
|
||||||
|
|
||||||
|
public function setUp(): void
|
||||||
|
{
|
||||||
|
$this->faker = Factory::create(locale: 'de_DE');
|
||||||
|
}
|
||||||
|
|
||||||
|
public function testCreateLayout(): void
|
||||||
|
{
|
||||||
|
$client = static::createClient();
|
||||||
|
|
||||||
|
$userRepository = static::getContainer()->get(ContactRepository::class);
|
||||||
|
|
||||||
|
$testUser = $userRepository->loadUserByUsername('admin@shop.de');
|
||||||
|
|
||||||
|
$client->loginUser($testUser, 'api');
|
||||||
|
|
||||||
|
$name = $this->faker->slug();
|
||||||
|
$client->jsonRequest(
|
||||||
|
'POST',
|
||||||
|
'/api/plugin/custom/psc/formbuilder/layouts/add',
|
||||||
|
[
|
||||||
|
'title' => $name,
|
||||||
|
'shop' => 'shop1234',
|
||||||
|
'data' => [
|
||||||
|
'uuid' => '5678987656789',
|
||||||
|
'name' => 'testlayout',
|
||||||
|
'options' => [
|
||||||
|
[
|
||||||
|
'type' => 1,
|
||||||
|
'name' => 'Auflage',
|
||||||
|
'id' => 'auflage',
|
||||||
|
],
|
||||||
|
],
|
||||||
|
],
|
||||||
|
],
|
||||||
|
[],
|
||||||
|
);
|
||||||
|
|
||||||
|
$this->assertResponseIsSuccessful();
|
||||||
|
$data = json_decode($client->getResponse()->getContent(), true);
|
||||||
|
self::assertSame($name, $data['title']);
|
||||||
|
|
||||||
|
$client->jsonRequest('GET', '/api/plugin/custom/psc/formbuilder/layouts/all/shop1234', [], []);
|
||||||
|
$this->assertResponseIsSuccessful();
|
||||||
|
$data = json_decode($client->getResponse()->getContent(), true);
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -19,6 +19,7 @@ class DesignTest extends WebTestCase
|
|||||||
'/api/plugin/system/psc/xmlcalc/product/design',
|
'/api/plugin/system/psc/xmlcalc/product/design',
|
||||||
[
|
[
|
||||||
'product' => '01938686-0e4d-7da9-bae3-b2e1b1681f9f',
|
'product' => '01938686-0e4d-7da9-bae3-b2e1b1681f9f',
|
||||||
|
'shop' => '771a1176-d531-48ed-93b8-eec1fd4b917f',
|
||||||
'jsonProduct' => json_decode(
|
'jsonProduct' => json_decode(
|
||||||
'[{"uuid":"df2df718-b28e-482d-bf0c-67d246f05d32","name":"Test Artikel","options":[{"id":"auflage","name":"Auflage","default":"100","dependencys":[],"placeHolder":"Placeholder","required":false,"type":2},{"id":"seiten_umschlag","name":"Seiten Umschlag","default":"2","dependencys":[],"placeHolder":"Placeholder","required":false,"type":2},{"id":"seiten_anzahl_inhalt","name":"Seiten Anzahl Inhalt","default":"10","dependencys":[{"relation":"auflage","formula":"","borders":[{"calcValue":"","calcValue1":"","calcValue2":"","calcValue3":"","calcValue4":"","calcValue5":"","calcValue6":"","calcValue7":"","calcValue8":"","calcValue9":"","calcValue10":"","flatRate":"","formula":"$Vauflage$V*0.12","price":0,"value":"1-10","dependencys":[{"relation":"seiten_umschlag","formula":"","borders":[{"calcValue":"","calcValue1":"","calcValue2":"","calcValue3":"","calcValue4":"","calcValue5":"","calcValue6":"","calcValue7":"","calcValue8":"","calcValue9":"","calcValue10":"","flatRate":"","formula":"$Vseiten_umschlag$V*0.24","price":0,"value":"1-2","dependencys":[]},{"calcValue":"","calcValue1":"","calcValue2":"","calcValue3":"","calcValue4":"","calcValue5":"","calcValue6":"","calcValue7":"","calcValue8":"","calcValue9":"","calcValue10":"","flatRate":"","formula":"$Vseiten_umschlag$V*0.23","price":0,"value":"3-","dependencys":[]}]}]},{"calcValue":"","calcValue1":"","calcValue2":"","calcValue3":"","calcValue4":"","calcValue5":"","calcValue6":"","calcValue7":"","calcValue8":"","calcValue9":"","calcValue10":"","flatRate":"","formula":"$Vauflage$V*0.11","price":0,"value":"11-","dependencys":[{"relation":"seiten_umschlag","formula":"","borders":[{"calcValue":"","calcValue1":"","calcValue2":"","calcValue3":"","calcValue4":"","calcValue5":"","calcValue6":"","calcValue7":"","calcValue8":"","calcValue9":"","calcValue10":"","flatRate":"","formula":"$Vseiten_umschlag$V*0.21","price":0,"value":"1-2","dependencys":[]},{"calcValue":"","calcValue1":"","calcValue2":"","calcValue3":"","calcValue4":"","calcValue5":"","calcValue6":"","calcValue7":"","calcValue8":"","calcValue9":"","calcValue10":"","flatRate":"","formula":"$Vseiten_umschlag$V*0.20","price":0,"value":"3-","dependencys":[]}]}]}]}],"placeHolder":"Placeholder","required":true,"type":2},{"id":"farbigkeit","name":"Farbigkeit","default":"10","dependencys":[],"type":3,"options":[{"id":"10","name":"1\/0 farbig","dependencys":[{"relation":"auflage","formula":"","borders":[{"calcValue":"","calcValue1":"","calcValue2":"","calcValue3":"","calcValue4":"","calcValue5":"","calcValue6":"","calcValue7":"","calcValue8":"","calcValue9":"","calcValue10":"","flatRate":"","formula":"","price":0,"value":"1-101","dependencys":[]}]}]},{"id":"11","name":"1\/1 farbig","dependencys":[]},{"id":"20","name":"2\/0 farbig","dependencys":[]},{"id":"21","name":"2\/1 farbig","dependencys":[]},{"id":"22","name":"2\/2 farbig","dependencys":[{"relation":"auflage","formula":"","borders":[{"calcValue":"","calcValue1":"","calcValue2":"","calcValue3":"","calcValue4":"","calcValue5":"","calcValue6":"","calcValue7":"","calcValue8":"","calcValue9":"","calcValue10":"","flatRate":"","formula":"","price":0,"value":"11-50","dependencys":[]}]}]}],"mode":"normal"},{"id":"calc","name":"calc","dependencys":[{"relation":"auflage","formula":"","borders":[{"calcValue":"","calcValue1":"","calcValue2":"","calcValue3":"","calcValue4":"","calcValue5":"","calcValue6":"","calcValue7":"","calcValue8":"","calcValue9":"","calcValue10":"","flatRate":"","formula":"$Vauflage$V*$Vseiten_anzahl_inhalt$V","price":0,"value":"1-","dependencys":[]}]}],"type":1}]}]',
|
'[{"uuid":"df2df718-b28e-482d-bf0c-67d246f05d32","name":"Test Artikel","options":[{"id":"auflage","name":"Auflage","default":"100","dependencys":[],"placeHolder":"Placeholder","required":false,"type":2},{"id":"seiten_umschlag","name":"Seiten Umschlag","default":"2","dependencys":[],"placeHolder":"Placeholder","required":false,"type":2},{"id":"seiten_anzahl_inhalt","name":"Seiten Anzahl Inhalt","default":"10","dependencys":[{"relation":"auflage","formula":"","borders":[{"calcValue":"","calcValue1":"","calcValue2":"","calcValue3":"","calcValue4":"","calcValue5":"","calcValue6":"","calcValue7":"","calcValue8":"","calcValue9":"","calcValue10":"","flatRate":"","formula":"$Vauflage$V*0.12","price":0,"value":"1-10","dependencys":[{"relation":"seiten_umschlag","formula":"","borders":[{"calcValue":"","calcValue1":"","calcValue2":"","calcValue3":"","calcValue4":"","calcValue5":"","calcValue6":"","calcValue7":"","calcValue8":"","calcValue9":"","calcValue10":"","flatRate":"","formula":"$Vseiten_umschlag$V*0.24","price":0,"value":"1-2","dependencys":[]},{"calcValue":"","calcValue1":"","calcValue2":"","calcValue3":"","calcValue4":"","calcValue5":"","calcValue6":"","calcValue7":"","calcValue8":"","calcValue9":"","calcValue10":"","flatRate":"","formula":"$Vseiten_umschlag$V*0.23","price":0,"value":"3-","dependencys":[]}]}]},{"calcValue":"","calcValue1":"","calcValue2":"","calcValue3":"","calcValue4":"","calcValue5":"","calcValue6":"","calcValue7":"","calcValue8":"","calcValue9":"","calcValue10":"","flatRate":"","formula":"$Vauflage$V*0.11","price":0,"value":"11-","dependencys":[{"relation":"seiten_umschlag","formula":"","borders":[{"calcValue":"","calcValue1":"","calcValue2":"","calcValue3":"","calcValue4":"","calcValue5":"","calcValue6":"","calcValue7":"","calcValue8":"","calcValue9":"","calcValue10":"","flatRate":"","formula":"$Vseiten_umschlag$V*0.21","price":0,"value":"1-2","dependencys":[]},{"calcValue":"","calcValue1":"","calcValue2":"","calcValue3":"","calcValue4":"","calcValue5":"","calcValue6":"","calcValue7":"","calcValue8":"","calcValue9":"","calcValue10":"","flatRate":"","formula":"$Vseiten_umschlag$V*0.20","price":0,"value":"3-","dependencys":[]}]}]}]}],"placeHolder":"Placeholder","required":true,"type":2},{"id":"farbigkeit","name":"Farbigkeit","default":"10","dependencys":[],"type":3,"options":[{"id":"10","name":"1\/0 farbig","dependencys":[{"relation":"auflage","formula":"","borders":[{"calcValue":"","calcValue1":"","calcValue2":"","calcValue3":"","calcValue4":"","calcValue5":"","calcValue6":"","calcValue7":"","calcValue8":"","calcValue9":"","calcValue10":"","flatRate":"","formula":"","price":0,"value":"1-101","dependencys":[]}]}]},{"id":"11","name":"1\/1 farbig","dependencys":[]},{"id":"20","name":"2\/0 farbig","dependencys":[]},{"id":"21","name":"2\/1 farbig","dependencys":[]},{"id":"22","name":"2\/2 farbig","dependencys":[{"relation":"auflage","formula":"","borders":[{"calcValue":"","calcValue1":"","calcValue2":"","calcValue3":"","calcValue4":"","calcValue5":"","calcValue6":"","calcValue7":"","calcValue8":"","calcValue9":"","calcValue10":"","flatRate":"","formula":"","price":0,"value":"11-50","dependencys":[]}]}]}],"mode":"normal"},{"id":"calc","name":"calc","dependencys":[{"relation":"auflage","formula":"","borders":[{"calcValue":"","calcValue1":"","calcValue2":"","calcValue3":"","calcValue4":"","calcValue5":"","calcValue6":"","calcValue7":"","calcValue8":"","calcValue9":"","calcValue10":"","flatRate":"","formula":"$Vauflage$V*$Vseiten_anzahl_inhalt$V","price":0,"value":"1-","dependencys":[]}]}],"type":1}]}]',
|
||||||
),
|
),
|
||||||
|
|||||||
35
src/new/tests/Plugins/System/PSC/XmlCalc/Api/PreviewTest.php
Normal file
35
src/new/tests/Plugins/System/PSC/XmlCalc/Api/PreviewTest.php
Normal file
@ -0,0 +1,35 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace Plugins\System\PSC\XmlCalc\Api;
|
||||||
|
|
||||||
|
use PSC\Shop\ContactBundle\Repository\ContactRepository;
|
||||||
|
use Symfony\Bundle\FrameworkBundle\Test\WebTestCase;
|
||||||
|
use Tests\RefreshDatabaseTrait;
|
||||||
|
|
||||||
|
class PreviewTest extends WebTestCase
|
||||||
|
{
|
||||||
|
use RefreshDatabaseTrait;
|
||||||
|
|
||||||
|
public function testSimplePreview(): void
|
||||||
|
{
|
||||||
|
$client = static::createClient();
|
||||||
|
|
||||||
|
$client->jsonRequest(
|
||||||
|
'POST',
|
||||||
|
'/api/plugin/system/psc/xmlcalc/product/pd',
|
||||||
|
[
|
||||||
|
'shop' => '771a1176-d531-48ed-93b8-eec1fd4b917f',
|
||||||
|
'json' => json_decode(
|
||||||
|
'[{"uuid":"2db72c84-67a9-4fcf-99da-9307255572af","name":"2f9152d2-2ce4-42ea-8f04-69484e0e8577","options":[{"id":"auflage","name":"Auflage","default":"100","dependencys":[{"relation":"auflage","formula":"","borders":[{"calcValue":"","calcValue1":"","calcValue2":"","calcValue3":"","calcValue4":"","calcValue5":"","calcValue6":"","calcValue7":"","calcValue8":"","calcValue9":"","calcValue10":"","flatRate":"","formula":"$Vauflage$V*0.12","price":0,"value":"1-","dependencys":[]}]}],"placeHolder":"Placeholder","required":true,"minValue":1,"maxValue":200,"minCalc":"","maxCalc":"","type":2}]}]',
|
||||||
|
),
|
||||||
|
'values' => ['auflage' => 100],
|
||||||
|
],
|
||||||
|
[],
|
||||||
|
);
|
||||||
|
$this->assertResponseIsSuccessful();
|
||||||
|
|
||||||
|
$data = json_decode($client->getResponse()->getContent(), true);
|
||||||
|
|
||||||
|
self::assertSame(1200, $data['netto']);
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -7,6 +7,7 @@ namespace Tests;
|
|||||||
use Doctrine\ODM\MongoDB\DocumentManager;
|
use Doctrine\ODM\MongoDB\DocumentManager;
|
||||||
use Doctrine\ORM\EntityManagerInterface;
|
use Doctrine\ORM\EntityManagerInterface;
|
||||||
use Hautelook\AliceBundle\PhpUnit\BaseDatabaseTrait;
|
use Hautelook\AliceBundle\PhpUnit\BaseDatabaseTrait;
|
||||||
|
use Plugin\Custom\PSC\FormBuilder\Document\Layout;
|
||||||
use PSC\Shop\ContactBundle\Model\AccountType;
|
use PSC\Shop\ContactBundle\Model\AccountType;
|
||||||
use PSC\Shop\EntityBundle\Document\Contact;
|
use PSC\Shop\EntityBundle\Document\Contact;
|
||||||
use PSC\Shop\EntityBundle\Document\Country;
|
use PSC\Shop\EntityBundle\Document\Country;
|
||||||
@ -53,11 +54,35 @@ trait RefreshDatabaseTrait
|
|||||||
$doc->getSchemaManager()->dropDocumentCollection(Order::class);
|
$doc->getSchemaManager()->dropDocumentCollection(Order::class);
|
||||||
$doc->getSchemaManager()->dropDocumentCollection(Position::class);
|
$doc->getSchemaManager()->dropDocumentCollection(Position::class);
|
||||||
$doc->getSchemaManager()->dropDocumentCollection(Instance::class);
|
$doc->getSchemaManager()->dropDocumentCollection(Instance::class);
|
||||||
|
$doc->getSchemaManager()->dropDocumentCollection(Plugin::class);
|
||||||
$doc->getSchemaManager()->dropDocumentCollection(Shop::class);
|
$doc->getSchemaManager()->dropDocumentCollection(Shop::class);
|
||||||
$doc->getSchemaManager()->dropDocumentCollection(Help::class);
|
$doc->getSchemaManager()->dropDocumentCollection(Help::class);
|
||||||
$doc->getSchemaManager()->dropDocumentCollection(Country::class);
|
$doc->getSchemaManager()->dropDocumentCollection(Country::class);
|
||||||
$doc->getSchemaManager()->dropDocumentCollection(Contact::class);
|
$doc->getSchemaManager()->dropDocumentCollection(Contact::class);
|
||||||
|
|
||||||
|
$bulk = new \MongoDB\Driver\BulkWrite();
|
||||||
|
$bulk->insert([
|
||||||
|
'name' => 'XML Kalkulations Produkt',
|
||||||
|
'installed' => true,
|
||||||
|
'shouldBeDeInstalled' => false,
|
||||||
|
'shouldBeInstalled' => false,
|
||||||
|
'path' => 'System/PSC/XmlCalc',
|
||||||
|
'namespace' => '\\Plugin\\System\\PSC\\XmlCalc\\Plugin',
|
||||||
|
'pluginId' => '19ff3fd21de9dbd7452fd0a67c928758',
|
||||||
|
]);
|
||||||
|
$bulk->insert([
|
||||||
|
'name' => 'FormBuilder',
|
||||||
|
'installed' => true,
|
||||||
|
'shouldBeDeInstalled' => false,
|
||||||
|
'shouldBeInstalled' => false,
|
||||||
|
'path' => 'Custom/PSC/FormBuilder',
|
||||||
|
'namespace' => '\\Plugin\\Custom\\PSC\\FormBuilder\\Plugin',
|
||||||
|
'pluginId' => '19ff3fd21de9dbd7452fd0a67c928759',
|
||||||
|
]);
|
||||||
|
$doc->getClient()->getManager()->executeBulkWrite('psc_test.Plugin', $bulk);
|
||||||
|
|
||||||
|
$doc->getSchemaManager()->dropDocumentCollection(Layout::class);
|
||||||
|
|
||||||
if (!$doc->getRepository(Plugin::class)->findOneBy(['pluginId' => '19ff3fd21de9dbd7452fd0a67c928758'])) {
|
if (!$doc->getRepository(Plugin::class)->findOneBy(['pluginId' => '19ff3fd21de9dbd7452fd0a67c928758'])) {
|
||||||
$plugin = new Plugin();
|
$plugin = new Plugin();
|
||||||
$plugin->setInstalled(true);
|
$plugin->setInstalled(true);
|
||||||
@ -70,6 +95,18 @@ trait RefreshDatabaseTrait
|
|||||||
$doc->clear();
|
$doc->clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (!$doc->getRepository(Plugin::class)->findOneBy(['pluginId' => '19ff3fd21de9dbd7452fd0a67c928759'])) {
|
||||||
|
$plugin = new Plugin();
|
||||||
|
$plugin->setInstalled(true);
|
||||||
|
$plugin->setPluginId('19ff3fd21de9dbd7452fd0a67c928759');
|
||||||
|
$plugin->setName('FormBuilder');
|
||||||
|
$plugin->setNamespace('\Plugin\Custom\PSC\FormBuilder\Plugin');
|
||||||
|
$plugin->setPath('Custom/PSC/FormBuilder');
|
||||||
|
$doc->persist($plugin);
|
||||||
|
$doc->flush();
|
||||||
|
$doc->clear();
|
||||||
|
}
|
||||||
|
|
||||||
$instance = new Instance();
|
$instance = new Instance();
|
||||||
$instance->setAppId('1');
|
$instance->setAppId('1');
|
||||||
$instance->setInvoiceNumberStart(1);
|
$instance->setInvoiceNumberStart(1);
|
||||||
|
|||||||
@ -0,0 +1,50 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace Plugin\Custom\PSC\FormBuilder\Api\Layout;
|
||||||
|
|
||||||
|
use Doctrine\ODM\MongoDB\DocumentManager;
|
||||||
|
use Nelmio\ApiDocBundle\Attribute\Model;
|
||||||
|
use Nelmio\ApiDocBundle\Attribute\Security;
|
||||||
|
use OpenApi\Attributes\JsonContent;
|
||||||
|
use OpenApi\Attributes\RequestBody;
|
||||||
|
use OpenApi\Attributes\Response;
|
||||||
|
use OpenApi\Attributes\Tag;
|
||||||
|
use Plugin\Custom\PSC\FormBuilder\Document\Layout as PSCLayout;
|
||||||
|
use Plugin\Custom\PSC\FormBuilder\Dto\Layout\Input;
|
||||||
|
use Plugin\Custom\PSC\FormBuilder\Model\Layout;
|
||||||
|
use Sensio\Bundle\FrameworkExtraBundle\Configuration\ParamConverter;
|
||||||
|
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
|
||||||
|
use Symfony\Component\Routing\Attribute\Route;
|
||||||
|
use Symfony\Component\Security\Http\Attribute\IsGranted;
|
||||||
|
|
||||||
|
class Add extends AbstractController
|
||||||
|
{
|
||||||
|
public function __construct(
|
||||||
|
private readonly DocumentManager $dm,
|
||||||
|
) {}
|
||||||
|
|
||||||
|
#[Response(response: 200, description: 'add layout', ref: Layout::class)]
|
||||||
|
#[Route(path: '/layouts/add', methods: ['POST'])]
|
||||||
|
#[Tag('FormBuilder')]
|
||||||
|
#[RequestBody(content: new Model(type: Input::class))]
|
||||||
|
#[ParamConverter('data', class: Input::class, converter: 'psc_rest.request_body')]
|
||||||
|
#[IsGranted('ROLE_ADMIN')]
|
||||||
|
#[Security(name: 'Security')]
|
||||||
|
public function add(Input $data)
|
||||||
|
{
|
||||||
|
$layout = new PSCLayout();
|
||||||
|
$layout->setTitle($data->title);
|
||||||
|
$layout->setData($data->data);
|
||||||
|
$layout->setShop($data->shop);
|
||||||
|
$this->dm->persist($layout);
|
||||||
|
$this->dm->flush();
|
||||||
|
|
||||||
|
$lModel = new Layout();
|
||||||
|
$lModel->setUuid($layout->getId());
|
||||||
|
$lModel->setTitle($layout->getTitle());
|
||||||
|
$lModel->setData($layout->getData());
|
||||||
|
$lModel->setShop($layout->getShop());
|
||||||
|
|
||||||
|
return $this->json($lModel);
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,58 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace Plugin\Custom\PSC\FormBuilder\Api\Layout;
|
||||||
|
|
||||||
|
use Doctrine\ODM\MongoDB\DocumentManager;
|
||||||
|
use MongoDB\BSON\ObjectId;
|
||||||
|
use Nelmio\ApiDocBundle\Attribute\Model;
|
||||||
|
use Nelmio\ApiDocBundle\Attribute\Security;
|
||||||
|
use OpenApi\Attributes\JsonContent;
|
||||||
|
use OpenApi\Attributes\Response;
|
||||||
|
use OpenApi\Attributes\Tag;
|
||||||
|
use Plugin\Custom\PSC\FormBuilder\Document\Layout;
|
||||||
|
use Plugin\Custom\PSC\FormBuilder\Dto\Layout\All as PluginAll;
|
||||||
|
use Plugin\Custom\PSC\FormBuilder\Model\Layout as PluginLayout;
|
||||||
|
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
|
||||||
|
use Symfony\Component\Routing\Attribute\Route;
|
||||||
|
use Symfony\Component\Security\Http\Attribute\IsGranted;
|
||||||
|
|
||||||
|
class All extends AbstractController
|
||||||
|
{
|
||||||
|
public function __construct(
|
||||||
|
private readonly DocumentManager $dm,
|
||||||
|
) {}
|
||||||
|
|
||||||
|
#[Response(
|
||||||
|
response: 200,
|
||||||
|
description: 'get all layouts',
|
||||||
|
content: new JsonContent(ref: new Model(type: PluginAll::class)),
|
||||||
|
)]
|
||||||
|
#[Route(path: '/layouts/all/{uuid}', methods: ['GET'])]
|
||||||
|
#[Tag('FormBuilder')]
|
||||||
|
#[IsGranted('ROLE_ADMIN')]
|
||||||
|
#[Security(name: 'Bearer')]
|
||||||
|
public function all(string $uuid)
|
||||||
|
{
|
||||||
|
$layouts = $this->dm
|
||||||
|
->getRepository(Layout::class)
|
||||||
|
->createQueryBuilder('layout')
|
||||||
|
->field('shop')
|
||||||
|
->equals($uuid)
|
||||||
|
->sort('title', 'ASC')
|
||||||
|
->getQuery()
|
||||||
|
->execute();
|
||||||
|
|
||||||
|
$output = new PluginAll();
|
||||||
|
|
||||||
|
foreach ($layouts as $layout) {
|
||||||
|
$l = new PluginLayout();
|
||||||
|
$l->setTitle($layout->getTitle());
|
||||||
|
$l->setUuid($layout->getId());
|
||||||
|
$l->setData($layout->getData());
|
||||||
|
$l->setShop($layout->getShop());
|
||||||
|
$l->setJson(json_encode($layout->getData()));
|
||||||
|
$output->data[] = $l;
|
||||||
|
}
|
||||||
|
return $this->json($output);
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,90 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace Plugin\Custom\PSC\FormBuilder\Document;
|
||||||
|
|
||||||
|
use Doctrine\ODM\MongoDB\Mapping\Annotations\Document;
|
||||||
|
use Doctrine\ODM\MongoDB\Mapping\Annotations\Field;
|
||||||
|
use Doctrine\ODM\MongoDB\Mapping\Annotations\Id;
|
||||||
|
|
||||||
|
#[Document(collection: 'formbuilder_layouts')]
|
||||||
|
class Layout
|
||||||
|
{
|
||||||
|
#[Id]
|
||||||
|
protected string $id;
|
||||||
|
#[Field(type: 'date')]
|
||||||
|
protected \DateTime $created;
|
||||||
|
#[Field(type: 'date')]
|
||||||
|
protected \DateTime $updated;
|
||||||
|
#[Field(type: 'string')]
|
||||||
|
protected string $title;
|
||||||
|
#[Field(type: 'string')]
|
||||||
|
protected string $shop;
|
||||||
|
#[Field(type: 'hash')]
|
||||||
|
protected array $data = [];
|
||||||
|
|
||||||
|
public function __construct()
|
||||||
|
{
|
||||||
|
$this->created = new \DateTime();
|
||||||
|
$this->updated = new \DateTime();
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getTitle(): string
|
||||||
|
{
|
||||||
|
return $this->title;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function setTitle(string $title): void
|
||||||
|
{
|
||||||
|
$this->title = $title;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getId(): string
|
||||||
|
{
|
||||||
|
return $this->id;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function setId(string $id): void
|
||||||
|
{
|
||||||
|
$this->id = $id;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getCreated(): \DateTime
|
||||||
|
{
|
||||||
|
return $this->created;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function setCreated(\DateTime $created): void
|
||||||
|
{
|
||||||
|
$this->created = $created;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getUpdated(): \DateTime
|
||||||
|
{
|
||||||
|
return $this->updated;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function setUpdated(\DateTime $updated): void
|
||||||
|
{
|
||||||
|
$this->updated = $updated;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getData(): array
|
||||||
|
{
|
||||||
|
return $this->data;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function setData(array $data): void
|
||||||
|
{
|
||||||
|
$this->data = $data;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getShop(): string
|
||||||
|
{
|
||||||
|
return $this->shop;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function setShop(string $shop): void
|
||||||
|
{
|
||||||
|
$this->shop = $shop;
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,16 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace Plugin\Custom\PSC\FormBuilder\Dto\Layout;
|
||||||
|
|
||||||
|
use Nelmio\ApiDocBundle\Attribute\Model;
|
||||||
|
use OpenApi\Attributes\Items;
|
||||||
|
use OpenApi\Attributes\Property;
|
||||||
|
use Plugin\Custom\PSC\FormBuilder\Model\Layout;
|
||||||
|
use Symfony\Component\Serializer\Attribute\MaxDepth;
|
||||||
|
|
||||||
|
final class All
|
||||||
|
{
|
||||||
|
#[Property(type: 'array', items: new Items(ref: new Model(type: Layout::class)))]
|
||||||
|
#[MaxDepth(4)]
|
||||||
|
public array $data;
|
||||||
|
}
|
||||||
@ -0,0 +1,21 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace Plugin\Custom\PSC\FormBuilder\Dto\Layout;
|
||||||
|
|
||||||
|
use OpenApi\Attributes\Items;
|
||||||
|
use OpenApi\Attributes\Property;
|
||||||
|
|
||||||
|
final class Input
|
||||||
|
{
|
||||||
|
#[Property(type: 'string')]
|
||||||
|
public string $title;
|
||||||
|
|
||||||
|
#[Property(type: 'string')]
|
||||||
|
public string $shop;
|
||||||
|
|
||||||
|
#[Property(type: 'array', items: new Items(
|
||||||
|
type: 'array',
|
||||||
|
items: new Items(),
|
||||||
|
))]
|
||||||
|
public array $data;
|
||||||
|
}
|
||||||
@ -11,7 +11,7 @@ onMounted(() => {
|
|||||||
const uuid = params.get('uuid')
|
const uuid = params.get('uuid')
|
||||||
const shopUuid = params.get('shop')
|
const shopUuid = params.get('shop')
|
||||||
const mode = params.get('mode')
|
const mode = params.get('mode')
|
||||||
globalStore.setProductUuid(shopUuid)
|
globalStore.setShopUuid(shopUuid)
|
||||||
globalStore.setMode(mode)
|
globalStore.setMode(mode)
|
||||||
if (uuid) {
|
if (uuid) {
|
||||||
globalStore.setProductUuid(uuid)
|
globalStore.setProductUuid(uuid)
|
||||||
@ -21,8 +21,22 @@ onMounted(() => {
|
|||||||
globalStore.loadFormulaAnalyserDataFromApi(uuid)
|
globalStore.loadFormulaAnalyserDataFromApi(uuid)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
let debounceTimer: number;
|
||||||
|
const debounce = (func: Function, delay: number) => {
|
||||||
|
return function(this: any, ...args: any[]) {
|
||||||
|
clearTimeout(debounceTimer);
|
||||||
|
debounceTimer = setTimeout(() => func.apply(this, args), delay);
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
const debouncedLoadPreview = debounce((json: object[]) => {
|
||||||
|
globalStore.loadPreview(json);
|
||||||
|
}, 500);
|
||||||
|
|
||||||
itemStore.$subscribe((mutation, state) => {
|
itemStore.$subscribe((mutation, state) => {
|
||||||
globalStore.saveDesign(itemStore.loadJSON());
|
const json = itemStore.loadJSON();
|
||||||
|
globalStore.saveDesign(json);
|
||||||
|
debouncedLoadPreview(json);
|
||||||
});
|
});
|
||||||
})
|
})
|
||||||
</script>
|
</script>
|
||||||
|
|||||||
@ -17,6 +17,9 @@ import XmlView from './app/XmlView.vue'
|
|||||||
import ParameterView from './app/ParameterView.vue'
|
import ParameterView from './app/ParameterView.vue'
|
||||||
import PaperDBView from './app/PaperDBView.vue'
|
import PaperDBView from './app/PaperDBView.vue'
|
||||||
import FormelView from './app/FormelView.vue'
|
import FormelView from './app/FormelView.vue'
|
||||||
|
import SaveLayoutDialog from './app/dialogs/SaveLayoutDialog.vue';
|
||||||
|
import LoadLayoutDialog from './app/dialogs/LoadLayoutDialog.vue';
|
||||||
|
import Preview from './app/preview/Preview.vue';
|
||||||
|
|
||||||
const globalStore = useGlobalStore()
|
const globalStore = useGlobalStore()
|
||||||
</script>
|
</script>
|
||||||
@ -62,7 +65,8 @@ const globalStore = useGlobalStore()
|
|||||||
</div>
|
</div>
|
||||||
<TabsContent value="designer" class="h-full overflow-y-auto">
|
<TabsContent value="designer" class="h-full overflow-y-auto">
|
||||||
<div class="flex h-full p-6">
|
<div class="flex h-full p-6">
|
||||||
<Main />
|
<Main v-if="!globalStore.showPreview" />
|
||||||
|
<Preview v-else />
|
||||||
</div>
|
</div>
|
||||||
</TabsContent>
|
</TabsContent>
|
||||||
<TabsContent value="preview" class="h-full overflow-y-auto">
|
<TabsContent value="preview" class="h-full overflow-y-auto">
|
||||||
@ -86,6 +90,8 @@ const globalStore = useGlobalStore()
|
|||||||
<ElementProperties />
|
<ElementProperties />
|
||||||
<SpecialElementProperties />
|
<SpecialElementProperties />
|
||||||
<ElementDependency />
|
<ElementDependency />
|
||||||
|
<SaveLayoutDialog />
|
||||||
|
<LoadLayoutDialog />
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|||||||
@ -7,12 +7,17 @@ const globalStore = useGlobalStore()
|
|||||||
function manualSave() {
|
function manualSave() {
|
||||||
globalStore.manualSave()
|
globalStore.manualSave()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function openSaveLayoutDialog() {
|
||||||
|
globalStore.setShowSaveLayoutDialog(true)
|
||||||
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
<div class="w-full p-2 flex">
|
<div class="w-full p-2 flex gap-2">
|
||||||
<Button @click="manualSave" :disabled="globalStore.saving">
|
<Button @click="manualSave" :disabled="globalStore.saving">
|
||||||
{{ globalStore.saving ? $t('saving') : $t('save') }}
|
{{ globalStore.saving ? $t('saving') : $t('save') }}
|
||||||
</Button>
|
</Button>
|
||||||
|
<Button @click="openSaveLayoutDialog" variant="outline">{{ $t('save_layout') }}</Button>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|||||||
@ -0,0 +1,68 @@
|
|||||||
|
<script setup lang="ts">
|
||||||
|
import { ref, onMounted } from 'vue';
|
||||||
|
import { Button } from '../../ui/button';
|
||||||
|
import {
|
||||||
|
Dialog,
|
||||||
|
DialogContent,
|
||||||
|
DialogDescription,
|
||||||
|
DialogHeader,
|
||||||
|
DialogTitle
|
||||||
|
} from '../../ui/dialog';
|
||||||
|
import { useGlobalStore } from '../../../stores/Global';
|
||||||
|
import { useItemStore } from '../../../stores/Items';
|
||||||
|
import { fetchLayouts } from '../../../lib/api';
|
||||||
|
import { useI18n } from 'vue-i18n';
|
||||||
|
|
||||||
|
const { t } = useI18n();
|
||||||
|
const globalStore = useGlobalStore();
|
||||||
|
const itemStore = useItemStore();
|
||||||
|
const layouts = ref<any[]>([]);
|
||||||
|
|
||||||
|
const loadLayouts = async () => {
|
||||||
|
try {
|
||||||
|
const response: any = await fetchLayouts(globalStore.getShopUuid);
|
||||||
|
layouts.value = response.data;
|
||||||
|
} catch (error) {
|
||||||
|
console.error('Failed to fetch layouts', error);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
const handleLoad = (layoutContent: string) => {
|
||||||
|
if (confirm(t('load_layout_confirm'))) {
|
||||||
|
itemStore.parseJSON(layoutContent);
|
||||||
|
globalStore.setShowLoadLayoutDialog(false);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
const onOpenChange = (open: boolean) => {
|
||||||
|
if (!open) {
|
||||||
|
globalStore.setShowLoadLayoutDialog(false);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
globalStore.$subscribe((mutation, state) => {
|
||||||
|
if(state.showLoadLayoutDialog) {
|
||||||
|
loadLayouts()
|
||||||
|
}
|
||||||
|
})
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<template>
|
||||||
|
<Dialog :open="globalStore.showLoadLayoutDialog" @update:open="onOpenChange">
|
||||||
|
<DialogContent>
|
||||||
|
<DialogHeader>
|
||||||
|
<DialogTitle>{{ $t('load_layout_title') }}</DialogTitle>
|
||||||
|
<DialogDescription>
|
||||||
|
{{ $t('load_layout_description') }}
|
||||||
|
</DialogDescription>
|
||||||
|
</DialogHeader>
|
||||||
|
<div class="grid gap-4 py-4">
|
||||||
|
<div v-for="layout in layouts" :key="layout.uuid" class="flex items-center justify-between">
|
||||||
|
<span>{{ layout.title }}</span>
|
||||||
|
<Button @click="handleLoad(layout.json)">{{ $t('load') }}</Button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</DialogContent>
|
||||||
|
</Dialog>
|
||||||
|
</template>
|
||||||
@ -0,0 +1,70 @@
|
|||||||
|
<script setup lang="ts">
|
||||||
|
import { ref } from 'vue';
|
||||||
|
import { Button } from '../../ui/button';
|
||||||
|
import { Input } from '../../ui/input';
|
||||||
|
import { Label } from '../../ui/label';
|
||||||
|
import {
|
||||||
|
Dialog,
|
||||||
|
DialogContent,
|
||||||
|
DialogDescription,
|
||||||
|
DialogFooter,
|
||||||
|
DialogHeader,
|
||||||
|
DialogTitle
|
||||||
|
} from '../../ui/dialog';
|
||||||
|
import { useGlobalStore } from '../../../stores/Global';
|
||||||
|
import { useItemStore } from '../../../stores/Items';
|
||||||
|
import { saveLayout } from '../../../lib/api';
|
||||||
|
import { useI18n } from 'vue-i18n';
|
||||||
|
|
||||||
|
const { t } = useI18n();
|
||||||
|
const globalStore = useGlobalStore();
|
||||||
|
const itemStore = useItemStore();
|
||||||
|
const layoutName = ref('');
|
||||||
|
|
||||||
|
const handleSave = async () => {
|
||||||
|
if (!layoutName.value) {
|
||||||
|
alert(t('enter_layout_name_alert'));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
try {
|
||||||
|
const layoutContent = itemStore.loadJSON();
|
||||||
|
await saveLayout(layoutName.value, globalStore.getShopUuid, layoutContent);
|
||||||
|
globalStore.setShowSaveLayoutDialog(false);
|
||||||
|
layoutName.value = '';
|
||||||
|
} catch (error) {
|
||||||
|
console.error('Failed to save layout', error);
|
||||||
|
alert(t('save_layout_failed_alert'));
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
const onOpenChange = (open: boolean) => {
|
||||||
|
if (!open) {
|
||||||
|
globalStore.setShowSaveLayoutDialog(false);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<template>
|
||||||
|
<Dialog :open="globalStore.showSaveLayoutDialog" @update:open="onOpenChange">
|
||||||
|
<DialogContent>
|
||||||
|
<DialogHeader>
|
||||||
|
<DialogTitle>{{ $t('save_layout_title') }}</DialogTitle>
|
||||||
|
<DialogDescription>
|
||||||
|
{{ $t('save_layout_description') }}
|
||||||
|
</DialogDescription>
|
||||||
|
</DialogHeader>
|
||||||
|
<div class="grid gap-4 py-4">
|
||||||
|
<div class="grid grid-cols-4 items-center gap-4">
|
||||||
|
<Label for="name" class="text-right">
|
||||||
|
{{ $t('name') }}
|
||||||
|
</Label>
|
||||||
|
<Input id="name" v-model="layoutName" class="col-span-3" />
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<DialogFooter>
|
||||||
|
<Button @click="handleSave">{{ $t('save_layout') }}</Button>
|
||||||
|
</DialogFooter>
|
||||||
|
</DialogContent>
|
||||||
|
</Dialog>
|
||||||
|
</template>
|
||||||
@ -3,6 +3,7 @@ import { useGlobalStore } from '../../../stores/Global'
|
|||||||
import { Image, Rows3, TableCellsMerge, SquareParking, SquareDot, SquareMenu, SquarePen, SquareChevronDown, SquareDashed, type LucideProps } from 'lucide-vue-next';
|
import { Image, Rows3, TableCellsMerge, SquareParking, SquareDot, SquareMenu, SquarePen, SquareChevronDown, SquareDashed, type LucideProps } from 'lucide-vue-next';
|
||||||
import { Switch } from '../../../components/ui/switch'
|
import { Switch } from '../../../components/ui/switch'
|
||||||
import { Label } from '../../../components/ui/label'
|
import { Label } from '../../../components/ui/label'
|
||||||
|
import { Button } from '../../../components/ui/button'
|
||||||
import { ref, watch, h } from 'vue'
|
import { ref, watch, h } from 'vue'
|
||||||
import { useI18n } from 'vue-i18n'
|
import { useI18n } from 'vue-i18n'
|
||||||
|
|
||||||
@ -20,6 +21,10 @@ function startDrag(event: DragEvent, item: string) {
|
|||||||
globalStore.setDragMode("insert")
|
globalStore.setDragMode("insert")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function openLoadLayoutDialog() {
|
||||||
|
globalStore.setShowLoadLayoutDialog(true)
|
||||||
|
}
|
||||||
|
|
||||||
watch(previewMode, (newPreviewMode) => {
|
watch(previewMode, (newPreviewMode) => {
|
||||||
if(newPreviewMode === false) {
|
if(newPreviewMode === false) {
|
||||||
globalStore.setShowPreview(false)
|
globalStore.setShowPreview(false)
|
||||||
@ -76,6 +81,10 @@ const renderIcon = (icon: any) => {
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
<div>
|
||||||
|
<Button @click="openLoadLayoutDialog" class="w-full">{{ $t('load_layout') }}</Button>
|
||||||
|
</div>
|
||||||
|
|
||||||
<div v-for="group in libraryItems" :key="group.category">
|
<div v-for="group in libraryItems" :key="group.category">
|
||||||
<h3 class="font-bold my-2">{{ $t(group.category) }}</h3>
|
<h3 class="font-bold my-2">{{ $t(group.category) }}</h3>
|
||||||
<div v-for="element in group.elements" :key="element.id"
|
<div v-for="element in group.elements" :key="element.id"
|
||||||
|
|||||||
@ -0,0 +1,42 @@
|
|||||||
|
<script setup lang="ts">
|
||||||
|
import { computed, watch } from 'vue'
|
||||||
|
import { useGlobalStore } from '../../../stores/Global'
|
||||||
|
import { Codemirror } from 'vue-codemirror'
|
||||||
|
import { json } from '@codemirror/lang-json'
|
||||||
|
import RenderElements from './RenderElements.vue'
|
||||||
|
import PriceDisplay from './PriceDisplay.vue';
|
||||||
|
const globalStore = useGlobalStore()
|
||||||
|
|
||||||
|
const previewData = computed(() => globalStore.getPreviewData)
|
||||||
|
const error = computed(() => globalStore.previewError)
|
||||||
|
const isLoading = computed(() => globalStore.isPreviewLoading)
|
||||||
|
|
||||||
|
const items = computed(() => previewData.value?.elements || [])
|
||||||
|
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<template>
|
||||||
|
<div class="w-full p-6 min-h-screen">
|
||||||
|
<div v-if="error" class="mb-4 bg-red-100 border-l-4 border-red-500 text-red-700 p-4" role="alert">
|
||||||
|
<p class="font-bold">Preview Error</p>
|
||||||
|
<p>{{ error }}</p>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div v-if="isLoading" class="text-center py-10">
|
||||||
|
<p>Loading Preview...</p>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div v-if="!isLoading && previewData">
|
||||||
|
<div class="overflow-auto h-full">
|
||||||
|
<div class="flex flex-row">
|
||||||
|
<div class="w-3/5 flex flex-col gap-2">
|
||||||
|
<RenderElements :items="items"/>
|
||||||
|
</div>
|
||||||
|
<div class="w-2/5 pl-6">
|
||||||
|
<PriceDisplay :tax="previewData.tax" :brutto="previewData.brutto" :netto="previewData.netto" />
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
@ -0,0 +1,39 @@
|
|||||||
|
<script setup lang="ts">
|
||||||
|
import { computed } from 'vue';
|
||||||
|
|
||||||
|
const props = defineProps<{
|
||||||
|
netto: any;
|
||||||
|
tax: any;
|
||||||
|
brutto: any;
|
||||||
|
}>();
|
||||||
|
|
||||||
|
const formatCurrency = (value: number) => {
|
||||||
|
return new Intl.NumberFormat('de-DE', { style: 'currency', currency: 'EUR' }).format(value);
|
||||||
|
};
|
||||||
|
|
||||||
|
const netPrice = computed(() => formatCurrency(props.netto/100 || 0));
|
||||||
|
const tax = computed(() => formatCurrency(props.tax/100 || 0));
|
||||||
|
const grossPrice = computed(() => formatCurrency(props.brutto/100 || 0));
|
||||||
|
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<template>
|
||||||
|
<div class="p-6 bg-gray-50 rounded-lg shadow-md">
|
||||||
|
<h3 class="text-lg font-semibold text-gray-800 mb-4">Preisübersicht</h3>
|
||||||
|
<div class="space-y-3">
|
||||||
|
<div class="flex justify-between items-center text-gray-600">
|
||||||
|
<span>Nettopreis</span>
|
||||||
|
<span class="font-medium text-gray-900">{{ netPrice }}</span>
|
||||||
|
</div>
|
||||||
|
<div class="flex justify-between items-center text-gray-600">
|
||||||
|
<span>+ MwSt. (19%)</span>
|
||||||
|
<span class="font-medium text-gray-900">{{ tax }}</span>
|
||||||
|
</div>
|
||||||
|
<hr class="my-3 border-t border-gray-200">
|
||||||
|
<div class="flex justify-between items-center text-xl font-bold">
|
||||||
|
<span class="text-gray-900">Gesamt</span>
|
||||||
|
<span class="text-primary">{{ grossPrice }}</span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
@ -0,0 +1,38 @@
|
|||||||
|
<script lang="ts" setup>
|
||||||
|
import { computed } from 'vue';
|
||||||
|
import TextElement from './elements/TextElement.vue'
|
||||||
|
import InputElement from './elements/InputElement.vue'
|
||||||
|
import HiddenElement from './elements/HiddenElement.vue'
|
||||||
|
import HeadlineElement from './elements/HeadlineElement.vue'
|
||||||
|
import SelectElement from './elements/SelectElement.vue'
|
||||||
|
|
||||||
|
const props = defineProps<{
|
||||||
|
items: any
|
||||||
|
}>()
|
||||||
|
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<template>
|
||||||
|
<div class="d-flex flex flex-col relative" v-for="item in items" v-if="items.length > 0" :key="item.uuid">
|
||||||
|
<HeadlineElement
|
||||||
|
v-if="item.valid && item.htmlType === 'headline'"
|
||||||
|
:item="item"
|
||||||
|
/>
|
||||||
|
<HiddenElement
|
||||||
|
v-if="item.valid && item.htmlType === 'hidden'"
|
||||||
|
:item="item"
|
||||||
|
/>
|
||||||
|
<InputElement
|
||||||
|
v-if="item.valid && item.htmlType === 'input'"
|
||||||
|
:item="item"
|
||||||
|
/>
|
||||||
|
<TextElement
|
||||||
|
v-if="item.valid && item.htmlType === 'text'"
|
||||||
|
:item="item"
|
||||||
|
/>
|
||||||
|
<SelectElement
|
||||||
|
v-if="item.valid && item.htmlType === 'select'"
|
||||||
|
:item="item"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
@ -0,0 +1,20 @@
|
|||||||
|
<script lang="ts" setup>
|
||||||
|
import { computed } from 'vue';
|
||||||
|
|
||||||
|
const props = defineProps<{
|
||||||
|
item: any
|
||||||
|
}>()
|
||||||
|
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<template>
|
||||||
|
<div class="flex gap-2 flex-row">
|
||||||
|
<h1 v-if="item.variant == '1'" class="text-4xl">{{item.defaultValue}}</h1>
|
||||||
|
<h6 v-else-if="item.variant == '6'" class="text-base">{{item.defaultValue}}</h6>
|
||||||
|
<h5 v-else-if="item.variant == '5'" class="text-lg">{{item.defaultValue}}</h5>
|
||||||
|
<h4 v-else-if="item.variant == '4'" class="text-xl">{{item.defaultValue}}</h4>
|
||||||
|
<h3 v-else-if="item.variant == '3'" class="text-2xl">{{item.defaultValue}}</h3>
|
||||||
|
<h2 v-else-if="item.variant == '2'" class="text-3xl">{{item.defaultValue}}</h2>
|
||||||
|
<h1 v-else class="text-4xl">{{item.defaultValue}}</h1>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
@ -0,0 +1,16 @@
|
|||||||
|
<script lang="ts" setup>
|
||||||
|
import { computed } from 'vue';
|
||||||
|
import { Input } from '../../../../components/ui/input'
|
||||||
|
|
||||||
|
const props = defineProps<{
|
||||||
|
item: any
|
||||||
|
}>()
|
||||||
|
|
||||||
|
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<template>
|
||||||
|
<div class="flex gap-2 flex-row">
|
||||||
|
<Input type="hidden" name="item.name" id="item.id" value="item.value"/>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
@ -0,0 +1,19 @@
|
|||||||
|
<script lang="ts" setup>
|
||||||
|
import { computed } from 'vue';
|
||||||
|
import { Input } from '../../../../components/ui/input'
|
||||||
|
import { useGlobalStore } from '../../../../stores/Global'
|
||||||
|
|
||||||
|
const props = defineProps<{
|
||||||
|
item: any
|
||||||
|
}>()
|
||||||
|
|
||||||
|
const globalStore = useGlobalStore()
|
||||||
|
</script>
|
||||||
|
|
||||||
|
|
||||||
|
<template>
|
||||||
|
<div class="flex gap-2 flex-row items-center">
|
||||||
|
<label class="w-60 flex-inital">{{item.name}}</label>
|
||||||
|
<Input v-model:placeholder="item.placeHolder" v-model="item.value" v-model:name="item.name" v-model:id="item.id" v-model:required="item.required"/>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
@ -0,0 +1,36 @@
|
|||||||
|
<script lang="ts" setup>
|
||||||
|
import { computed } from 'vue'
|
||||||
|
import {
|
||||||
|
Select,
|
||||||
|
SelectContent,
|
||||||
|
SelectGroup,
|
||||||
|
SelectItem,
|
||||||
|
SelectTrigger,
|
||||||
|
SelectValue,
|
||||||
|
} from '../../../../components/ui/select'
|
||||||
|
|
||||||
|
const props = defineProps<{
|
||||||
|
item: any
|
||||||
|
}>()
|
||||||
|
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<template>
|
||||||
|
<div class="flex gap-2 flex-row items-center">
|
||||||
|
<label class="w-60 flex-inital">{{item.name}}</label>
|
||||||
|
<div class="w-full">
|
||||||
|
<Select v-model="item.rawValue">
|
||||||
|
<SelectTrigger>
|
||||||
|
<SelectValue />
|
||||||
|
</SelectTrigger>
|
||||||
|
<SelectContent>
|
||||||
|
<SelectGroup>
|
||||||
|
<SelectItem v-for="option in item.options" :key="option.uuid" :value="option.id">
|
||||||
|
{{option.name}}
|
||||||
|
</SelectItem>
|
||||||
|
</SelectGroup>
|
||||||
|
</SelectContent>
|
||||||
|
</Select>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
@ -0,0 +1,14 @@
|
|||||||
|
<script lang="ts" setup>
|
||||||
|
import { computed } from 'vue';
|
||||||
|
|
||||||
|
const props = defineProps<{
|
||||||
|
item: any
|
||||||
|
}>()
|
||||||
|
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<template>
|
||||||
|
<div class="flex gap-2 flex-row">
|
||||||
|
<p style="white-space: pre-line;">{{item.defaultValue}}</p>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
@ -34,18 +34,6 @@ const itemStore = useItemStore()
|
|||||||
const globalStore = useGlobalStore()
|
const globalStore = useGlobalStore()
|
||||||
|
|
||||||
const dragUuid = ref("")
|
const dragUuid = ref("")
|
||||||
let isPreview = ref(false)
|
|
||||||
|
|
||||||
isPreview.value = globalStore.showPreview
|
|
||||||
|
|
||||||
globalStore.$subscribe((mutation, state) => {
|
|
||||||
if(state.showPreview) {
|
|
||||||
isPreview.value = true
|
|
||||||
}else{
|
|
||||||
isPreview.value = false
|
|
||||||
}
|
|
||||||
})
|
|
||||||
|
|
||||||
const startDrag = (event: DragEvent, uuid: string) => {
|
const startDrag = (event: DragEvent, uuid: string) => {
|
||||||
event.dataTransfer!.dropEffect = 'move'
|
event.dataTransfer!.dropEffect = 'move'
|
||||||
event.dataTransfer!.effectAllowed = 'move'
|
event.dataTransfer!.effectAllowed = 'move'
|
||||||
@ -108,14 +96,14 @@ const editElementDependency = (item: BaseElement) => {
|
|||||||
<div class="overflow-auto h-full">
|
<div class="overflow-auto h-full">
|
||||||
<div class="flex flex-col gap-2">
|
<div class="flex flex-col gap-2">
|
||||||
<div class="d-flex flex flex-col relative items-center" v-for="item in items" v-if="items.length > 0" :key="item.uuid">
|
<div class="d-flex flex flex-col relative items-center" v-for="item in items" v-if="items.length > 0" :key="item.uuid">
|
||||||
<div class="w-full" v-if="item.type !== 1 || (item.type === 1 && !isPreview) ">
|
<div class="w-full" v-if="item.type !== 1 || (item.type === 1) ">
|
||||||
<div class="h-8 group w-full" @dragleave.self="dragLeave($event, item.uuid)" @dragenter.self="dragEnter($event, item.uuid)" @drop="stopDrag($event, item.uuid)" v-if="!isPreview">
|
<div class="h-8 group w-full" @dragleave.self="dragLeave($event, item.uuid)" @dragenter.self="dragEnter($event, item.uuid)" @drop="stopDrag($event, item.uuid)">
|
||||||
<div class="inline-flex items-center justify-center w-full pointer-events-none">
|
<div class="inline-flex items-center justify-center w-full pointer-events-none">
|
||||||
<hr class="w-64 h-px my-2 bg-gray-200 border-0 dark:bg-gray-700 transition duration-200 pointer-events-none" :class="{ 'bg-orange-500': dragUuid == item.uuid }" >
|
<hr class="w-64 h-px my-2 bg-gray-200 border-0 dark:bg-gray-700 transition duration-200 pointer-events-none" :class="{ 'bg-orange-500': dragUuid == item.uuid }" >
|
||||||
<span class="absolute px-3 font-medium text-gray-900 -translate-x-1/2 bg-white left-1/2 dark:text-white dark:bg-gray-900 pointer-events-none"><CirclePlus :class="{ 'text-orange-500': dragUuid == item.uuid }" class="transition duration-200 pointer-events-none" /></span>
|
<span class="absolute px-3 font-medium text-gray-900 -translate-x-1/2 bg-white left-1/2 dark:text-white dark:bg-gray-900 pointer-events-none"><CirclePlus :class="{ 'text-orange-500': dragUuid == item.uuid }" class="transition duration-200 pointer-events-none" /></span>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div :class="{ 'border-white' : !item.hasDependencys() || isPreview, 'border-blue-500': item.hasDependencys() && !isPreview }" @dragstart="startDrag($event, item.uuid)" draggable="true" class="element w-full flex flex-row border-l-2 hover:border-orange-500 pl-2 transition duration-500 min-h-5" v-bind:class="{ ' bg-slate-50': item.isFocused === true }">
|
<div :class="{ 'border-white' : !item.hasDependencys() , 'border-blue-500': item.hasDependencys() }" @dragstart="startDrag($event, item.uuid)" draggable="true" class="element w-full flex flex-row border-l-2 hover:border-orange-500 pl-2 transition duration-500 min-h-5" v-bind:class="{ ' bg-slate-50': item.isFocused === true }">
|
||||||
<div class="grow content-center items-center">
|
<div class="grow content-center items-center">
|
||||||
<InputElementForm
|
<InputElementForm
|
||||||
v-if="item.type === 2"
|
v-if="item.type === 2"
|
||||||
@ -154,7 +142,7 @@ const editElementDependency = (item: BaseElement) => {
|
|||||||
v-model="item as MediaElement"
|
v-model="item as MediaElement"
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
<div class="buttons absolute rounded-sm invisible right-0 bg-slate-100/70 flex flex-row gap-2" v-if="!isPreview">
|
<div class="buttons absolute rounded-sm invisible right-0 bg-slate-100/70 flex flex-row gap-2">
|
||||||
<div v-on:click="editElementDependency(item)" :title="$t('dependencies')" class="m-2 cursor-pointer">
|
<div v-on:click="editElementDependency(item)" :title="$t('dependencies')" class="m-2 cursor-pointer">
|
||||||
<Option />
|
<Option />
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@ -50,5 +50,15 @@
|
|||||||
"sync": "Synchronisieren",
|
"sync": "Synchronisieren",
|
||||||
"cms_elements": "CMS-Elemente",
|
"cms_elements": "CMS-Elemente",
|
||||||
"form_elements": "Formular-Elemente",
|
"form_elements": "Formular-Elemente",
|
||||||
"structure_elements": "Struktur-Elemente"
|
"structure_elements": "Struktur-Elemente",
|
||||||
|
"save_layout": "Layout speichern",
|
||||||
|
"load_layout": "Vorlage laden",
|
||||||
|
"save_layout_title": "Layout speichern",
|
||||||
|
"save_layout_description": "Gib einen Namen für deine neue Layout-Vorlage ein.",
|
||||||
|
"load_layout_title": "Vorlage laden",
|
||||||
|
"load_layout_description": "Wähle eine Layout-Vorlage aus, um sie in den Designer zu laden.",
|
||||||
|
"load": "Laden",
|
||||||
|
"enter_layout_name_alert": "Bitte gib einen Namen für das Layout ein.",
|
||||||
|
"save_layout_failed_alert": "Layout konnte nicht gespeichert werden.",
|
||||||
|
"load_layout_confirm": "Möchtest du dieses Layout wirklich laden? Dein aktuelles Design wird überschrieben."
|
||||||
}
|
}
|
||||||
@ -50,5 +50,15 @@
|
|||||||
"sync": "Sync",
|
"sync": "Sync",
|
||||||
"cms_elements": "CMS Elements",
|
"cms_elements": "CMS Elements",
|
||||||
"form_elements": "Form Elements",
|
"form_elements": "Form Elements",
|
||||||
"structure_elements": "Structure Elements"
|
"structure_elements": "Structure Elements",
|
||||||
|
"save_layout": "Save Layout",
|
||||||
|
"load_layout": "Load Layout",
|
||||||
|
"save_layout_title": "Save Layout",
|
||||||
|
"save_layout_description": "Enter a name for your new layout template.",
|
||||||
|
"load_layout_title": "Load Layout",
|
||||||
|
"load_layout_description": "Select a layout template to load it into the designer.",
|
||||||
|
"load": "Load",
|
||||||
|
"enter_layout_name_alert": "Please enter a name for the layout.",
|
||||||
|
"save_layout_failed_alert": "Failed to save layout.",
|
||||||
|
"load_layout_confirm": "Are you sure you want to load this layout? This will overwrite your current design."
|
||||||
}
|
}
|
||||||
@ -48,9 +48,9 @@ export const loadPriceFromApi = async (uuid: string) => {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
export const saveDesignToApi = async (uuid: string, json: object[]) => {
|
export const saveDesignToApi = async (uuid: string, shopUuid: string, json: object[]) => {
|
||||||
try {
|
try {
|
||||||
const response = await api.post('api/plugin/system/psc/xmlcalc/product/design', { json: { product: uuid, jsonProduct: json } });
|
const response = await api.post('api/plugin/system/psc/xmlcalc/product/design', { json: { product: uuid, shop: shopUuid, jsonProduct: json } });
|
||||||
return await response.json();
|
return await response.json();
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error('Error saving design to API:', error);
|
console.error('Error saving design to API:', error);
|
||||||
@ -144,4 +144,34 @@ export const fetchMediaByFolder = async (folderId: string, page: number = 1) =>
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
export const saveLayout = async (name: string, shop: string, data: object[]) => {
|
||||||
|
try {
|
||||||
|
const response = await api.post('api/plugin/custom/psc/formbuilder/layouts/add', { json: { title: name, data: data, shop: shop } });
|
||||||
|
return await response.json();
|
||||||
|
} catch (error) {
|
||||||
|
console.error('Error saving layout:', error);
|
||||||
|
throw error;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
export const fetchLayouts = async (shop: string) => {
|
||||||
|
try {
|
||||||
|
const response = await api.get('api/plugin/custom/psc/formbuilder/layouts/all/' + shop);
|
||||||
|
return await response.json();
|
||||||
|
} catch (error) {
|
||||||
|
console.error('Error fetching layouts:', error);
|
||||||
|
throw error;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
export const fetchPreview = async (shopUuid: string, json: object[]) => {
|
||||||
|
try {
|
||||||
|
const response = await api.post('api/plugin/system/psc/xmlcalc/product/pd', { json: { shop: shopUuid, json: json } });
|
||||||
|
return await response.json();
|
||||||
|
} catch (error) {
|
||||||
|
console.error('Error fetching preview:', error);
|
||||||
|
throw error;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
export default api;
|
export default api;
|
||||||
|
|||||||
@ -1,7 +1,7 @@
|
|||||||
import { defineStore } from 'pinia'
|
import { defineStore } from 'pinia'
|
||||||
import BaseElement from '../model/BaseElement'
|
import BaseElement from '../model/BaseElement'
|
||||||
import Mode from '../model/Mode'
|
import Mode from '../model/Mode'
|
||||||
import { saveProductToApi, saveFomulasAndParameterToApi, loadJsonFromApi, loadPriceFromApi, savePaperContainerToApi, saveDesignToApi, saveXmlToApi } from '../lib/api'
|
import { saveProductToApi, saveFomulasAndParameterToApi, loadJsonFromApi, loadPriceFromApi, savePaperContainerToApi, saveDesignToApi, saveXmlToApi, fetchPreview } from '../lib/api'
|
||||||
import { useItemStore } from './Items'
|
import { useItemStore } from './Items'
|
||||||
|
|
||||||
export const useGlobalStore = defineStore('global', {
|
export const useGlobalStore = defineStore('global', {
|
||||||
@ -15,6 +15,8 @@ export const useGlobalStore = defineStore('global', {
|
|||||||
showDependency: false,
|
showDependency: false,
|
||||||
showOptions: false,
|
showOptions: false,
|
||||||
showPreview: false,
|
showPreview: false,
|
||||||
|
showSaveLayoutDialog: false,
|
||||||
|
showLoadLayoutDialog: false,
|
||||||
sourceDragUuid: "",
|
sourceDragUuid: "",
|
||||||
dragMode: "",
|
dragMode: "",
|
||||||
json: "",
|
json: "",
|
||||||
@ -27,6 +29,9 @@ export const useGlobalStore = defineStore('global', {
|
|||||||
saving: false,
|
saving: false,
|
||||||
syncing: false,
|
syncing: false,
|
||||||
currentTab: 'designer' as string | number,
|
currentTab: 'designer' as string | number,
|
||||||
|
previewData: {} as object,
|
||||||
|
isPreviewLoading: false,
|
||||||
|
previewError: '',
|
||||||
}),
|
}),
|
||||||
getters: {
|
getters: {
|
||||||
getActiveItem: (state) => state.activeItem as BaseElement,
|
getActiveItem: (state) => state.activeItem as BaseElement,
|
||||||
@ -35,9 +40,11 @@ export const useGlobalStore = defineStore('global', {
|
|||||||
isShowOptions: (state) => state.showOptions,
|
isShowOptions: (state) => state.showOptions,
|
||||||
isShowPreview: (state) => state.showPreview,
|
isShowPreview: (state) => state.showPreview,
|
||||||
getSourceDragUuid: (state) => state.sourceDragUuid,
|
getSourceDragUuid: (state) => state.sourceDragUuid,
|
||||||
|
getShopUuid: (state) => state.shopUuid,
|
||||||
getDragMode: (state) => state.dragMode,
|
getDragMode: (state) => state.dragMode,
|
||||||
getFormulaData: (state) => state.formulaData,
|
getFormulaData: (state) => state.formulaData,
|
||||||
getFormulaError: (state) => state.formulaError,
|
getFormulaError: (state) => state.formulaError,
|
||||||
|
getPreviewData: (state) => state.previewData,
|
||||||
},
|
},
|
||||||
actions: {
|
actions: {
|
||||||
setXml(value: string) {
|
setXml(value: string) {
|
||||||
@ -82,6 +89,12 @@ export const useGlobalStore = defineStore('global', {
|
|||||||
setDragMode(mode: string) {
|
setDragMode(mode: string) {
|
||||||
this.dragMode = mode
|
this.dragMode = mode
|
||||||
},
|
},
|
||||||
|
setShowSaveLayoutDialog(value: boolean) {
|
||||||
|
this.showSaveLayoutDialog = value
|
||||||
|
},
|
||||||
|
setShowLoadLayoutDialog(value: boolean) {
|
||||||
|
this.showLoadLayoutDialog = value
|
||||||
|
},
|
||||||
setShopUuid(value: string) {
|
setShopUuid(value: string) {
|
||||||
this.shopUuid = value
|
this.shopUuid = value
|
||||||
},
|
},
|
||||||
@ -122,7 +135,7 @@ export const useGlobalStore = defineStore('global', {
|
|||||||
this.json = json
|
this.json = json
|
||||||
},
|
},
|
||||||
saveDesign(json: object[]) {
|
saveDesign(json: object[]) {
|
||||||
saveDesignToApi(this.productUuid, json).then((result: any) => {
|
saveDesignToApi(this.productUuid, this.shopUuid, json).then((result: any) => {
|
||||||
this.setXML(result.xml)
|
this.setXML(result.xml)
|
||||||
this.setJSON(result.json)
|
this.setJSON(result.json)
|
||||||
this.formulaData = JSON.parse(result.jsonGraph);
|
this.formulaData = JSON.parse(result.jsonGraph);
|
||||||
@ -162,6 +175,19 @@ export const useGlobalStore = defineStore('global', {
|
|||||||
},
|
},
|
||||||
setCurrentTab(tab: string | number) {
|
setCurrentTab(tab: string | number) {
|
||||||
this.currentTab = tab
|
this.currentTab = tab
|
||||||
|
},
|
||||||
|
async loadPreview(json: object[]) {
|
||||||
|
this.isPreviewLoading = true;
|
||||||
|
this.previewError = '';
|
||||||
|
try {
|
||||||
|
const response: any = await fetchPreview(this.shopUuid, json);
|
||||||
|
this.previewData = response;
|
||||||
|
} catch (e: any) {
|
||||||
|
this.previewError = `Failed to load preview data: ${e.message}`;
|
||||||
|
console.error(e);
|
||||||
|
} finally {
|
||||||
|
this.isPreviewLoading = false;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|||||||
@ -33,7 +33,7 @@ export default defineConfig({
|
|||||||
changeOrigin: true,
|
changeOrigin: true,
|
||||||
configure: (proxy) => {
|
configure: (proxy) => {
|
||||||
proxy.on('proxyReq', (proxyReq) => {
|
proxy.on('proxyReq', (proxyReq) => {
|
||||||
proxyReq.setHeader('Authorization', 'Bearer eyJ0eXAiOiJKV1QiLCJhbGciOiJSUzI1NiJ9.eyJpYXQiOjE3NTQzMjQwMzAsImV4cCI6MTc1NDMyNzYzMCwicm9sZXMiOlsiUk9MRV9BRE1JTiIsIlJPTEVfU0hPUF9PUEVSQVRPUiIsIlJPTEVfVVNFUiIsIlJPTEVfVVNFUiIsIlJPTEVfUFNDX0NvbGxlY3RfQ29udGFjdF9FZGl0IiwiUk9MRV9QU0NfQ29sbGVjdF9Db250YWN0X0FkZCIsIlJPTEVfUFNDX0NvbGxlY3RfQ29udGFjdF9EZWxldGUiLCJST0xFX1BTQ19Db2xsZWN0X0NvbnRhY3RfTG9jayIsIlJPTEVfUFNDX1IyX1NlbmRjbG91ZF9TaG93Il0sInVpZCI6MX0.JQV0pGK1C_9sL4-0zLlXBzwMV8tUwCLis9KDUC_5DVOZf8Ujb0Yqgmie9B9DISAGvjtWUSvuUzcbcsV4m2gkNN-6dar-Y6XCC54KbkVCAOhssMp3KsZ1pbCiZ_VdUt78WbAFMkvhToHjjdpD4KqhetQjqFlGF1jYXfJmFzRDHh0YnUfYZDsqgun423JeUXbRYB0sJ3FLQzCuyUDWFvdsQVwCGsgs0ffkro42qMbLXZtdRPaAPZTlEYbE5H-wck1iKvAeEgNuqGJEnk-oEy6UQ1mGUHz7NT5N7NmXhkca2byInCMXhDPn2tmQvte5AKUAte0GELt3FjF5rhk1Iu2rZw');
|
proxyReq.setHeader('Authorization', 'Bearer eyJ0eXAiOiJKV1QiLCJhbGciOiJSUzI1NiJ9.eyJpYXQiOjE3NTQ1OTUxMjUsImV4cCI6MTc1NDU5ODcyNSwicm9sZXMiOlsiUk9MRV9BRE1JTiIsIlJPTEVfU0hPUF9PUEVSQVRPUiIsIlJPTEVfVVNFUiIsIlJPTEVfVVNFUiIsIlJPTEVfUFNDX0NvbGxlY3RfQ29udGFjdF9FZGl0IiwiUk9MRV9QU0NfQ29sbGVjdF9Db250YWN0X0FkZCIsIlJPTEVfUFNDX0NvbGxlY3RfQ29udGFjdF9EZWxldGUiLCJST0xFX1BTQ19Db2xsZWN0X0NvbnRhY3RfTG9jayIsIlJPTEVfUFNDX1IyX1NlbmRjbG91ZF9TaG93Il0sInVpZCI6MX0.C-_PO6C-uFj_6zOtJymfYRsMi0tn-Aq_-HAjpYIqh4rAvY5fTnf54kli1F1bqYogRTqWiTgzPh3EYkPuU7dC8UlCN1eMwXzLFzqtlI7IPPh2UhUvFv6EGix5XTWHnfO-I53vYhrd1qO5Kp--nqFyCCMSaXsRd9daJ7fkbPfGXrwIXPxUeFhhcbMYP4SsUHgS3ZGInM1J_txO62LJHBc91pAtzSliVpUhwJzHjHuiTeC8WTUhdRgVaQo2echLWPfPrMlWolh3cN6wk41wCNivpTIQ4h-a3WVEHvlRz61W9jehzWMiMoTZglmatn8cPsiFFb_nmUacYP5avazXAdpgjA');
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
|||||||
76
src/new/var/plugins/Custom/PSC/FormBuilder/Model/Layout.php
Normal file
76
src/new/var/plugins/Custom/PSC/FormBuilder/Model/Layout.php
Normal file
@ -0,0 +1,76 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace Plugin\Custom\PSC\FormBuilder\Model;
|
||||||
|
|
||||||
|
use OpenApi\Attributes as OA;
|
||||||
|
|
||||||
|
class Layout
|
||||||
|
{
|
||||||
|
#[OA\Property(type: 'string')]
|
||||||
|
private string $title = '';
|
||||||
|
|
||||||
|
#[OA\Property(type: 'string')]
|
||||||
|
private string $uuid = '';
|
||||||
|
|
||||||
|
#[OA\Property(type: 'string')]
|
||||||
|
private string $shop = '';
|
||||||
|
|
||||||
|
#[Property(type: 'array', items: new Items(
|
||||||
|
type: 'array',
|
||||||
|
items: new Items(),
|
||||||
|
))]
|
||||||
|
private array $data;
|
||||||
|
|
||||||
|
#[OA\Property(type: 'string')]
|
||||||
|
private string $json = '';
|
||||||
|
|
||||||
|
public function getTitle(): string
|
||||||
|
{
|
||||||
|
return $this->title;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function setTitle(string $title): void
|
||||||
|
{
|
||||||
|
$this->title = $title;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getUuid(): string
|
||||||
|
{
|
||||||
|
return $this->uuid;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function setUuid(string $uuid): void
|
||||||
|
{
|
||||||
|
$this->uuid = $uuid;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getData(): array
|
||||||
|
{
|
||||||
|
return $this->data;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function setData(array $data): void
|
||||||
|
{
|
||||||
|
$this->data = $data;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getJson(): string
|
||||||
|
{
|
||||||
|
return $this->json;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function setJson(string $json): void
|
||||||
|
{
|
||||||
|
$this->json = $json;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getShop(): string
|
||||||
|
{
|
||||||
|
return $this->shop;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function setShop(string $shop): void
|
||||||
|
{
|
||||||
|
$this->shop = $shop;
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,4 @@
|
|||||||
|
api_platform:
|
||||||
|
mapping:
|
||||||
|
paths:
|
||||||
|
- './../../Model'
|
||||||
@ -1,6 +1,9 @@
|
|||||||
psc_backend_component_formbuilder:
|
plugin_custom_psc_formbuilder:
|
||||||
resource: "@PluginCustomPSCFormBuilder/Controller/Backend"
|
resource: "@PluginCustomPSCFormBuilder/Controller/Backend"
|
||||||
type: annotation
|
type: annotation
|
||||||
prefix: /backend/component/formbuilder
|
prefix: /backend/component/formbuilder
|
||||||
|
|
||||||
|
plugin_system_psc_formbuilder_api:
|
||||||
|
resource: "@PluginCustomPSCFormBuilder/Api"
|
||||||
|
type: annotation
|
||||||
|
prefix: /api/plugin/custom/psc/formbuilder
|
||||||
|
|||||||
@ -57,27 +57,28 @@ class Design extends AbstractController
|
|||||||
->getRepository('PSC\Shop\EntityBundle\Entity\Product')
|
->getRepository('PSC\Shop\EntityBundle\Entity\Product')
|
||||||
->findOneBy(['uuid' => $data->product]);
|
->findOneBy(['uuid' => $data->product]);
|
||||||
|
|
||||||
|
$selectedShop = $this->shopService->getShopByUid($data->shop);
|
||||||
|
|
||||||
$paperContainer = new PaperContainer();
|
$paperContainer = new PaperContainer();
|
||||||
$paperContainer->parse(simplexml_load_string($product->getShop()->getInstall()->getPaperContainer()));
|
$paperContainer->parse(simplexml_load_string($selectedShop->getInstall()->getPaperContainer()));
|
||||||
$engine = new Engine();
|
$engine = new Engine();
|
||||||
$engine->setPaperRepository($this->paperDB);
|
$engine->setPaperRepository($this->paperDB);
|
||||||
$engine->setPaperContainer($paperContainer);
|
$engine->setPaperContainer($paperContainer);
|
||||||
if ($product->getShop()->getInstall()->getCalcTemplates() && !$data->test) {
|
if ($selectedShop->getInstall()->getCalcTemplates() && !$data->test) {
|
||||||
$engine->setTemplates('<root>' . $product->getShop()->getInstall()->getCalcTemplates() . '</root>');
|
$engine->setTemplates('<root>' . $selectedShop->getInstall()->getCalcTemplates() . '</root>');
|
||||||
}
|
}
|
||||||
if ($product->getShop()->getInstall()->getCalcTemplatesTest() && $data->test) {
|
if ($selectedShop->getInstall()->getCalcTemplatesTest() && $data->test) {
|
||||||
$engine->setTemplates('<root>' . $product->getShop()->getInstall()->getCalcTemplatesTest() . '</root>');
|
$engine->setTemplates('<root>' . $selectedShop->getInstall()->getCalcTemplatesTest() . '</root>');
|
||||||
}
|
}
|
||||||
$engine->loadJson(json_encode($data->jsonProduct));
|
$engine->loadJson(json_encode($data->jsonProduct));
|
||||||
if (!$data->test) {
|
if (!$data->test) {
|
||||||
$engine->setFormulas($product->getShop()->getFormel());
|
$engine->setFormulas($selectedShop->getFormel());
|
||||||
$engine->setParameters($product->getShop()->getParameter());
|
$engine->setParameters($selectedShop->getParameter());
|
||||||
}
|
}
|
||||||
if ($data->test) {
|
if ($data->test) {
|
||||||
$engine->setFormulas($product->getShop()->getTestFormel());
|
$engine->setFormulas($selectedShop->getTestFormel());
|
||||||
$engine->setParameters($product->getShop()->getTestParameter());
|
$engine->setParameters($selectedShop->getTestParameter());
|
||||||
}
|
}
|
||||||
// $engine->setVariables($data->values);
|
|
||||||
$engine->setTax($product->getMwert());
|
$engine->setTax($product->getMwert());
|
||||||
if ($this->tokenStorage->getToken()) {
|
if ($this->tokenStorage->getToken()) {
|
||||||
$contact = new Contact();
|
$contact = new Contact();
|
||||||
@ -90,12 +91,12 @@ class Design extends AbstractController
|
|||||||
return $this->json([
|
return $this->json([
|
||||||
'json' => $engine->generateJson(),
|
'json' => $engine->generateJson(),
|
||||||
'parameter' => $engine->getParameters(),
|
'parameter' => $engine->getParameters(),
|
||||||
'paperContainer' => $product->getShop()->getInstall()->getPaperContainer(),
|
'paperContainer' => $selectedShop->getInstall()->getPaperContainer(),
|
||||||
'formulas' => $engine->getFormulas(),
|
'formulas' => $engine->getFormulas(),
|
||||||
'xml' => $engine->generateXML(true),
|
'xml' => $engine->generateXML(true),
|
||||||
'jsonGraph' => $engine->getCalcGraph()->generateJsonGraph(),
|
'jsonGraph' => $engine->getCalcGraph()->generateJsonGraph(),
|
||||||
'price' => $engine->getPrice() * 100,
|
'price' => $engine->getPrice() * 100,
|
||||||
'shopUuid' => $product->getShop()->getUid(),
|
'shopUuid' => $selectedShop->getUid(),
|
||||||
]);
|
]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -0,0 +1,206 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace Plugin\System\PSC\XmlCalc\Api\Product;
|
||||||
|
|
||||||
|
use Doctrine\ODM\MongoDB\DocumentManager;
|
||||||
|
use Doctrine\ORM\EntityManagerInterface;
|
||||||
|
use Nelmio\ApiDocBundle\Attribute\Model;
|
||||||
|
use OpenApi\Attributes\JsonContent;
|
||||||
|
use OpenApi\Attributes\RequestBody;
|
||||||
|
use OpenApi\Attributes\Response as OpenApiResponse;
|
||||||
|
use OpenApi\Attributes\Tag;
|
||||||
|
use Plugin\System\PSC\XmlCalc\Dto\Input\PDInput;
|
||||||
|
use Plugin\System\PSC\XmlCalc\Dto\Output\Display\Group as DisplayGroup;
|
||||||
|
use Plugin\System\PSC\XmlCalc\Dto\Output\Price\Element;
|
||||||
|
use Plugin\System\PSC\XmlCalc\Dto\Output\Price\Option;
|
||||||
|
use Plugin\System\PSC\XmlCalc\Dto\Output\Price\Validation\Input\Max as PluginMax;
|
||||||
|
use Plugin\System\PSC\XmlCalc\Dto\Output\Price\Validation\Input\Min;
|
||||||
|
use PSC\Library\Calc\Engine;
|
||||||
|
use PSC\Library\Calc\Error\Validation\Input\Max;
|
||||||
|
use PSC\Library\Calc\Error\Validation\Input\Min as PSCMin;
|
||||||
|
use PSC\Library\Calc\Option\Type\Base;
|
||||||
|
use PSC\Library\Calc\Option\Type\ColorDBSelect;
|
||||||
|
use PSC\Library\Calc\Option\Type\DeliverySelect;
|
||||||
|
use PSC\Library\Calc\Option\Type\Select\Opt;
|
||||||
|
use PSC\Library\Calc\PaperContainer;
|
||||||
|
use PSC\Shop\ContactBundle\Model\Contact;
|
||||||
|
use PSC\Shop\ContactBundle\Transformer\Model\Contact as ContactTransformer;
|
||||||
|
use PSC\System\SettingsBundle\Service\Help;
|
||||||
|
use PSC\System\SettingsBundle\Service\PaperDB;
|
||||||
|
use Sensio\Bundle\FrameworkExtraBundle\Configuration\ParamConverter;
|
||||||
|
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
|
||||||
|
use Symfony\Component\Routing\Attribute\Route;
|
||||||
|
use Symfony\Component\Security\Core\Authentication\Token\Storage\TokenStorageInterface;
|
||||||
|
|
||||||
|
class PreviewDesigner extends AbstractController
|
||||||
|
{
|
||||||
|
private \PSC\System\SettingsBundle\Service\Shop $shopService;
|
||||||
|
/**
|
||||||
|
* @var DocumentManager
|
||||||
|
*/
|
||||||
|
private DocumentManager $documentManager;
|
||||||
|
/**
|
||||||
|
* @var PaperDB
|
||||||
|
*/
|
||||||
|
private PaperDB $paperDB;
|
||||||
|
/**
|
||||||
|
* @var EntityManagerInterface
|
||||||
|
*/
|
||||||
|
private EntityManagerInterface $entityManager;
|
||||||
|
|
||||||
|
private TokenStorageInterface $tokenStorage;
|
||||||
|
private ContactTransformer $contactTransformer;
|
||||||
|
|
||||||
|
private Help $helpService;
|
||||||
|
|
||||||
|
public function __construct(
|
||||||
|
\PSC\System\SettingsBundle\Service\Shop $shopService,
|
||||||
|
DocumentManager $documentManager,
|
||||||
|
EntityManagerInterface $entityManager,
|
||||||
|
PaperDB $paperDB,
|
||||||
|
ContactTransformer $contactTransformer,
|
||||||
|
TokenStorageInterface $tokenStorage,
|
||||||
|
Help $helpService,
|
||||||
|
) {
|
||||||
|
$this->shopService = $shopService;
|
||||||
|
$this->documentManager = $documentManager;
|
||||||
|
$this->entityManager = $entityManager;
|
||||||
|
$this->tokenStorage = $tokenStorage;
|
||||||
|
$this->paperDB = $paperDB;
|
||||||
|
$this->contactTransformer = $contactTransformer;
|
||||||
|
$this->helpService = $helpService;
|
||||||
|
}
|
||||||
|
|
||||||
|
#[Route(path: '/product/pd', methods: ['POST'])]
|
||||||
|
#[OpenApiResponse(
|
||||||
|
response: 200,
|
||||||
|
description: 'generate preview for new designer',
|
||||||
|
content: new JsonContent(ref: new Model(type: PDOutput::class)),
|
||||||
|
)]
|
||||||
|
#[Tag(name: 'Plugin/System/psc/Xmlcalc/Price')]
|
||||||
|
#[RequestBody(ref: new Model(type: PDInput::class))]
|
||||||
|
#[ParamConverter('data', class: '\Plugin\System\PSC\XmlCalc\Dto\Input\PDInput', converter: 'psc_rest.request_body')]
|
||||||
|
public function preview(PDInput $data)
|
||||||
|
{
|
||||||
|
$output = new \Plugin\System\PSC\XmlCalc\Dto\Output\Product\PDOutput();
|
||||||
|
|
||||||
|
$shop = $this->shopService->getShopByUid($data->shop);
|
||||||
|
|
||||||
|
$paperContainer = new PaperContainer();
|
||||||
|
$paperContainer->parse(simplexml_load_string($shop->getInstall()->getPaperContainer()));
|
||||||
|
$engine = new Engine();
|
||||||
|
$engine->setPaperRepository($this->paperDB);
|
||||||
|
$engine->setPaperContainer($paperContainer);
|
||||||
|
$engine->setTemplates('<root>' . $shop->getInstall()->getCalcTemplates() . '</root>');
|
||||||
|
$engine->loadJson(json_encode($data->json));
|
||||||
|
$engine->setFormulas($shop->getFormel());
|
||||||
|
$engine->setParameters($shop->getParameter());
|
||||||
|
$engine->setVariables($data->values);
|
||||||
|
if ($this->tokenStorage->getToken()) {
|
||||||
|
$contact = new Contact();
|
||||||
|
$this->contactTransformer->fromDb($contact, $this->tokenStorage->getToken()->getUser());
|
||||||
|
$engine->setVariable('contact.accountType', $contact->getAccountType()->value);
|
||||||
|
$engine->setVariable('contact.account', $contact->getAccount()->getUid());
|
||||||
|
}
|
||||||
|
|
||||||
|
$engine->setTax(19);
|
||||||
|
$output->netto = $engine->getPrice() * 100;
|
||||||
|
$output->tax = $engine->getTaxPrice() * 100;
|
||||||
|
$output->brutto = $engine->getCompletePrice() * 100;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @var Base $option
|
||||||
|
*/
|
||||||
|
foreach ($engine->getArticle()->getOptions() as $option) {
|
||||||
|
$tmp = new Element();
|
||||||
|
$tmp->name = $option->getName();
|
||||||
|
$tmp->required = $option->isRequire();
|
||||||
|
if (is_array($option->getRawValue())) {
|
||||||
|
$tmp->rawValues = $option->getRawValue();
|
||||||
|
} else {
|
||||||
|
$tmp->rawValue = $option->getRawValue();
|
||||||
|
}
|
||||||
|
if ($option->getDefault()) {
|
||||||
|
$tmp->defaultValue = $option->getDefault();
|
||||||
|
}
|
||||||
|
$tmp->value = $option->getValue();
|
||||||
|
|
||||||
|
if ($help = $this->helpService->getHelp(null, $option->getId())) {
|
||||||
|
$tmp->help = $help->helpText;
|
||||||
|
$tmp->helpTitle = $help->helpTitle;
|
||||||
|
} else {
|
||||||
|
$tmp->help = $option->getHelp();
|
||||||
|
$tmp->helpLink = $option->getHelpLink();
|
||||||
|
}
|
||||||
|
$tmp->id = $option->getId();
|
||||||
|
$tmp->valid = $option->isValid();
|
||||||
|
$tmp->htmlType = $option->type;
|
||||||
|
$tmp->displayGroup = $option->getDisplayGroup();
|
||||||
|
|
||||||
|
if ($option->type == 'select' || $option->type == 'checkbox' || $option->type == 'radio') {
|
||||||
|
/**
|
||||||
|
* @var Opt $option
|
||||||
|
*/
|
||||||
|
if ($option instanceof ColorDBSelect) {
|
||||||
|
$tmp->colorSystem = $option->getColorSystem();
|
||||||
|
if (!isset($output->colorDb[$option->getColorSystem()])) {
|
||||||
|
$output->colorDb[$option->getColorSystem()] = [];
|
||||||
|
foreach ($option->getOptions() as $opt) {
|
||||||
|
$element = array_find((array) $option->getSelectedOptions(), function (Opt $o1) use ($opt) {
|
||||||
|
return $o1->getId() === $opt->getId();
|
||||||
|
});
|
||||||
|
$tmpOpt = new Option();
|
||||||
|
$tmpOpt->id = $opt->getId();
|
||||||
|
$tmpOpt->name = $opt->getLabel();
|
||||||
|
$tmpOpt->prefix = $opt->getPrefix();
|
||||||
|
$tmpOpt->suffix = $opt->getSuffix();
|
||||||
|
$tmpOpt->valid = $opt->isValid();
|
||||||
|
$tmpOpt->selected = $element ? true : false;
|
||||||
|
$output->colorDb[$option->getColorSystem()][] = $tmpOpt;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
foreach ($option->getOptions() as $opt) {
|
||||||
|
$element = array_find((array) $option->getSelectedOptions(), function (Opt $o1) use ($opt) {
|
||||||
|
return $o1->getId() === $opt->getId();
|
||||||
|
});
|
||||||
|
|
||||||
|
if ($option instanceof DeliverySelect) {
|
||||||
|
$tmpOpt = new Option();
|
||||||
|
$tmpOpt->id = $opt->getId();
|
||||||
|
$tmpOpt->name = $opt->getLabel();
|
||||||
|
$tmpOpt->valid = $opt->isValid();
|
||||||
|
$tmpOpt->selected = $element ? true : false;
|
||||||
|
$tmpOpt->info = $opt->getInfo();
|
||||||
|
$tmpOpt->deliveryDate = $opt->getDeliveryDateAsString();
|
||||||
|
} else {
|
||||||
|
$tmpOpt = new Option();
|
||||||
|
$tmpOpt->id = $opt->getId();
|
||||||
|
$tmpOpt->name = $opt->getLabel();
|
||||||
|
$tmpOpt->valid = $opt->isValid();
|
||||||
|
$tmpOpt->selected = $element ? true : false;
|
||||||
|
}
|
||||||
|
$tmp->options[] = $tmpOpt;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if ($option->type == 'input') {
|
||||||
|
$tmp->minValue = $option->getMinValue();
|
||||||
|
$tmp->maxValue = $option->getMaxValue();
|
||||||
|
$tmp->placeHolder = $option->getPlaceHolder();
|
||||||
|
$tmp->pattern = $option->getPattern();
|
||||||
|
foreach ($option->getValidationErrors() as $error) {
|
||||||
|
if ($error instanceof PSCMin) {
|
||||||
|
$tmp->validationErrors[] = new Min($tmp->value, $option->getMinValue());
|
||||||
|
}
|
||||||
|
if ($error instanceof Max) {
|
||||||
|
$tmp->validationErrors[] = new PluginMax($tmp->value, $option->getMaxValue());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
$output->elements[] = $tmp;
|
||||||
|
}
|
||||||
|
return $this->json($output);
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -2,36 +2,27 @@
|
|||||||
|
|
||||||
namespace Plugin\System\PSC\XmlCalc\Dto\Input;
|
namespace Plugin\System\PSC\XmlCalc\Dto\Input;
|
||||||
|
|
||||||
use Nelmio\ApiDocBundle\Annotation\Model;
|
use OpenApi\Attributes as OA;
|
||||||
use OpenApi\Annotations as OA;
|
use OpenApi\Attributes\Items;
|
||||||
|
use OpenApi\Attributes\Property;
|
||||||
|
|
||||||
final class DesignInput
|
final class DesignInput
|
||||||
{
|
{
|
||||||
/**
|
#[Property(type: 'string')]
|
||||||
* @var string
|
|
||||||
*
|
|
||||||
* @OA\Property(type="string")
|
|
||||||
*/
|
|
||||||
public string $product;
|
public string $product;
|
||||||
|
|
||||||
/**
|
#[Property(type: 'string')]
|
||||||
* @var array
|
public string $shop;
|
||||||
*
|
|
||||||
* @OA\Property(type="array", @OA\Items(type="array", @OA\Items()))
|
#[Property(type: 'array', items: new Items(
|
||||||
*/
|
type: 'array',
|
||||||
|
items: new Items(),
|
||||||
|
))]
|
||||||
public array $jsonProduct = [];
|
public array $jsonProduct = [];
|
||||||
|
|
||||||
/**
|
#[Property(type: 'boolean')]
|
||||||
* @var bool
|
|
||||||
*
|
|
||||||
* @OA\Property(type="boolean")
|
|
||||||
*/
|
|
||||||
public bool $test = false;
|
public bool $test = false;
|
||||||
|
|
||||||
/**
|
#[Property(type: 'array', items: new Items(type: 'string'))]
|
||||||
* @var array
|
|
||||||
*
|
|
||||||
* @OA\Property(type="array", @OA\Items(type="string"))
|
|
||||||
*/
|
|
||||||
public array $values = ['auflage' => 100];
|
public array $values = ['auflage' => 100];
|
||||||
}
|
}
|
||||||
|
|||||||
21
src/new/var/plugins/System/PSC/XmlCalc/Dto/Input/PDInput.php
Normal file
21
src/new/var/plugins/System/PSC/XmlCalc/Dto/Input/PDInput.php
Normal file
@ -0,0 +1,21 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace Plugin\System\PSC\XmlCalc\Dto\Input;
|
||||||
|
|
||||||
|
use OpenApi\Attributes\Items;
|
||||||
|
use OpenApi\Attributes\Property;
|
||||||
|
|
||||||
|
final class PDInput
|
||||||
|
{
|
||||||
|
#[Property(type: 'string')]
|
||||||
|
public string $shop;
|
||||||
|
|
||||||
|
#[Property(type: 'array', items: new Items(
|
||||||
|
type: 'array',
|
||||||
|
items: new Items(),
|
||||||
|
))]
|
||||||
|
public array $json = [];
|
||||||
|
|
||||||
|
#[Property(type: 'array', items: new Items(type: 'string'))]
|
||||||
|
public array $values = ['auflage' => 100];
|
||||||
|
}
|
||||||
@ -0,0 +1,32 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace Plugin\System\PSC\XmlCalc\Dto\Output\Product;
|
||||||
|
|
||||||
|
use Nelmio\ApiDocBundle\Attribute\Model;
|
||||||
|
use OpenApi\Attributes\Items;
|
||||||
|
use OpenApi\Attributes\Property;
|
||||||
|
use Plugin\System\PSC\XmlCalc\Dto\Output\Price\Element;
|
||||||
|
|
||||||
|
final class PDOutput
|
||||||
|
{
|
||||||
|
#[Property(type: 'boolean')]
|
||||||
|
public $success = true;
|
||||||
|
|
||||||
|
#[Property(type: 'int')]
|
||||||
|
public int $netto;
|
||||||
|
|
||||||
|
#[Property(type: 'int')]
|
||||||
|
public int $tax;
|
||||||
|
|
||||||
|
#[Property(type: 'int')]
|
||||||
|
public int $brutto;
|
||||||
|
|
||||||
|
#[Property(type: 'array', items: new Items(
|
||||||
|
type: 'array',
|
||||||
|
items: new Items(),
|
||||||
|
))]
|
||||||
|
public array $colorDb = [];
|
||||||
|
|
||||||
|
#[Property(type: 'array', items: new Items(ref: new Model(type: Element::class)))]
|
||||||
|
public array $elements = [];
|
||||||
|
}
|
||||||
File diff suppressed because it is too large
Load Diff
Loading…
Reference in New Issue
Block a user