Skip to content
This repository was archived by the owner on Feb 13, 2023. It is now read-only.

Commit 4dee66e

Browse files
authored
Merge pull request #51 from ergonode/develop
Release
2 parents 2094f22 + b20d5f4 commit 4dee66e

21 files changed

+627
-159
lines changed

docs/_coverpage.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
<p align="center">
22
<a href="https://ergonode.com" rel="noopener noreferrer">
3-
<img width="500" src="https://ergonode.com/img/logo-dark.svg" alt="Ergonode logo">
3+
<img width="500" src="images/logo-dark.svg" alt="Ergonode logo">
44
</a>
55
</p>
66

docs/_sidebar.md

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,8 @@
33
* [**Backend - development**](installation/backend-development.md)
44
* [**Backend - contribution**](installation/backend-contribution.md)
55
<!-- * [**Backend - production**](installation/backend-production.md) -->
6-
* [**Frontend**](installation/frontend.md)
6+
* [**Frontend - development**](installation/frontend-development.md)
7+
* [**Frontend - contribution**](installation/frontend-contribution.md)
78
* [**Docker - contribution**](installation/docker.md)
89
* [**Documentation**](installation/docs.md)
910
* [**Backend**](backend.md)
@@ -63,6 +64,8 @@
6364
* [**Extend Toolbar Menu**](frontend/cookbook/extend_toolbar_menu.md)
6465
* [**In depth**](frontend/in-depth/in-depth.md)
6566
* [**Autosave**](frontend/in-depth/autosave.md)
67+
* [**i18n**](frontend/in-depth/i18n.md)
68+
* [**axios**](frontend/in-depth/axios.md)
6669
* [**Community**](community.md)
6770
* [Contribution](community/contribution.md)
6871
* [Code of Conduct](community/code_of_conduct.md)

docs/backend/configuration.md

Lines changed: 9 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -13,15 +13,16 @@ Configuration is available in .env file in the main directory.
1313
| DATABASE_URL | Database connection | pgsql://postgres:123@127.0.0.1:5432/ergonode | |
1414
| JWT_PRIVATE_KEY_PATH | path to private JWT key file | config/jwt/private.pem | |
1515
| JWT_PUBLIC_KEY_PATH | path to public JWT key file | config/jwt/public.pem | |
16-
| JWT_PASSPHRASE | JWT Key password | 1234 | |
17-
| JWT_TOKEN_TTL | JWT Token lifetime in seconds | 86400 | |
16+
| JWT_PASSPHRASE | JSON Web Token Key password | 1234 | |
17+
| JWT_TOKEN_TTL | JSON Web Token lifetime in seconds | 86400 | |
18+
| JWT_REFRESH_TOKEN_TTL | Refresh JSON Web Token lifetime in seconds | 604800 | |
1819
| CORS_ALLOW_ORIGIN | Cors access address | ^http?://localhost:3000\|$ | |
1920
| USE_ASYNC_BUS | Use asynchronous mode | false | |
20-
| MESSENGER_TRANSPORT_DSN | Default messenger queue in rabbit | amqp://guest:guest@localhost:5672/%2f/messages | |
21-
| MESSENGER_TRANSPORT_IMPORT_DSN | Import messenger queue in rabbit | amqp://guest:guest@localhost:5672/%2f/imports | |
21+
| MESSENGER_TRANSPORT_COMPLETENESS_DSN | Completeness messenger queue in rabbit | amqp://guest:guest@localhost:5672/%2f/completeness | |
2222
| MESSENGER_TRANSPORT_CORE_DSN | Core messenger queue in rabbit | amqp://guest:guest@localhost:5672/%2f/core | |
2323
| MESSENGER_TRANSPORT_EXPORT_DSN | Export messenger queue in rabbit | amqp://guest:guest@localhost:5672/%2f/exports | |
24-
| MESSENGER_TRANSPORT_DOMAIN_DSN | Domain event messenger queue in rabbit | amqp://guest:guest@localhost:5672/%2f/domain | |
25-
| MESSENGER_TRANSPORT_CHANNEL_DSN | Channel messenger queue in rabbit | amqp://guest:guest@localhost:5672/%2f/channel | |
26-
| MESSENGER_TRANSPORT_COMPLETENESS_DSN | Completeness messenger queue in rabbit | amqp://guest:guest@localhost:5672/%2f/completeness | |
27-
| MESSENGER_TRANSPORT_SEGMENT_DSN | Segment messenger queue in rabbit | amqp://guest:guest@localhost:5672/%2f/segment | |
24+
| MESSENGER_TRANSPORT_IMPORT_DSN | Import messenger queue in rabbit | amqp://guest:guest@localhost:5672/%2f/imports | |
25+
| MESSENGER_TRANSPORT_NOTIFICATION_DSN | Notification event messenger queue in rabbit | amqp://guest:guest@localhost:5672/%2f/notification | |
26+
| MESSENGER_TRANSPORT_SEGMENT_DSN | Segment messenger queue in rabbit | amqp://guest:guest@localhost:5672/%2f/segment | |
27+
| MAILER_DSN | Mailing server address | null://null | |
28+
| MAILER_SENDER | Sender of the e-mail | dev@ergonode.com | |

docs/backend/cookbook.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,5 +11,6 @@
1111
* [New Condition](backend/cookbook/new_condition.md)
1212
* [New Channel](backend/cookbook/new_channel.md)
1313
* [New Mass Action](backend/cookbook/new_mass_action.md)
14+
* [New Import Source](backend/cookbook/new_source.md)
1415

1516

docs/backend/cookbook/new_channel.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,8 +2,8 @@
22
# How to create a new channel
33

44
Channel
5-
* Entity Claas to management
6-
* external service connector(if required)
5+
* Entity Class to management
6+
* external service connector (if required)
77
* specific configuration of a specific target system
88

99
In your channel [module].

docs/backend/cookbook/new_source.md

Lines changed: 244 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,244 @@
1+
# How to create new import source
2+
3+
## Source class
4+
5+
Any custom source class must extend```AbstractSource```
6+
7+
This class is used to define a new type of Source to appear in the application and can be used to store the necessary configuration data
8+
9+
```php
10+
namespace YourNameSpace\Domain\Entity;
11+
12+
use Ergonode\SharedKernel\Domain\Aggregate\SourceId;
13+
use Ergonode\Importer\Domain\Entity\Source\AbstractSource;
14+
15+
class YourSource extends AbstractSource
16+
{
17+
public const TYPE = 'your-source-type';
18+
19+
public function __construct(SourceId $id, string $name)
20+
{
21+
parent::__construct($id, $name);
22+
}
23+
24+
public function getType(): string
25+
{
26+
return self::TYPE;
27+
}
28+
}
29+
```
30+
31+
## Source class configuration
32+
33+
You need create Form class for configuration Your Source.
34+
35+
Only "name" field is required, other are dependent from you needs.
36+
37+
```php
38+
namespace YourNameSpace\Application\Form;
39+
40+
use YourNameSpace\Application\Model\YourSourceConfigurationModel;
41+
use Symfony\Component\Form\AbstractType;
42+
use Symfony\Component\Form\Extension\Core\Type\TextType;
43+
use Symfony\Component\Form\FormBuilderInterface;
44+
use Symfony\Component\OptionsResolver\OptionsResolver;
45+
46+
class YourSourceConfigurationForm extends AbstractType
47+
{
48+
/**
49+
* @param array $options
50+
*/
51+
public function buildForm(FormBuilderInterface $builder, array $options): void
52+
{
53+
$builder
54+
->add(
55+
'name',
56+
TextType::class,
57+
[
58+
'label' => 'Name',
59+
]
60+
);
61+
}
62+
63+
public function configureOptions(OptionsResolver $resolver): void
64+
{
65+
$resolver->setDefaults([
66+
'translation_domain' => 'importer',
67+
'data_class' => YourSourceConfigurationModel::class,
68+
'allow_extra_fields' => true,
69+
'label' => 'Import settings',
70+
]);
71+
}
72+
73+
public function getBlockPrefix(): ?string
74+
{
75+
return null;
76+
}
77+
}
78+
```
79+
80+
Configuration Model class
81+
82+
```php
83+
namespace YourNameSpace\Application\Model;
84+
85+
use Symfony\Component\Validator\Constraints as Assert;
86+
use YourNameSpace\Domain\Entity\YourSource;
87+
88+
class YourSourceConfigurationModel
89+
{
90+
/**
91+
* @Assert\NotBlank()
92+
* @Assert\Length(min=2)
93+
*/
94+
public ?string $name = null;
95+
96+
public function __construct(YourSource $source = null)
97+
{
98+
if ($source) {
99+
$this->name = $source->getName();
100+
}
101+
}
102+
}
103+
```
104+
105+
For providing form need to add ```YourSourceFormFactory``` class.
106+
107+
```php
108+
namespace YourNameSpace\Application\Factory;
109+
110+
use Ergonode\Importer\Domain\Entity\Source\AbstractSource;
111+
use YourNameSpace\Domain\Entity\YourSource;
112+
use Symfony\Component\Form\FormFactoryInterface;
113+
use YourNamespace\Application\Form\YourSourceConfigurationForm;
114+
use Symfony\Component\Form\FormInterface;
115+
use YourNamespace\Application\Model\YourSourceConfigurationModel;
116+
use Ergonode\Importer\Application\Provider\SourceFormFactoryInterface;
117+
use Symfony\Component\HttpFoundation\Request;
118+
119+
class YourSourceFormFactory implements SourceFormFactoryInterface
120+
{
121+
private FormFactoryInterface $formFactory;
122+
123+
public function __construct(FormFactoryInterface $formFactory)
124+
{
125+
$this->formFactory = $formFactory;
126+
}
127+
128+
public function supported(string $type): bool
129+
{
130+
return YourSource::TYPE === $type;
131+
}
132+
133+
public function create(AbstractSource $source = null): FormInterface
134+
{
135+
$model = new YourSourceConfigurationModel($source);
136+
if (null === $source) {
137+
return $this->formFactory->create(YourSourceConfigurationForm::class, $model);
138+
}
139+
140+
return $this->formFactory->create(
141+
YourSourceConfigurationForm::class,
142+
$model,
143+
['method' => Request::METHOD_PUT]
144+
);
145+
}
146+
}
147+
```
148+
149+
Next step is to create Source Manipulation Commands and Handlers
150+
151+
```php
152+
namespace YourNameSpace\Domain\Command;
153+
154+
use Ergonode\Importer\Domain\Command\CreateSourceCommandInterface;
155+
use Ergonode\SharedKernel\Domain\Aggregate\SourceId;
156+
use JMS\Serializer\Annotation as JMS;
157+
158+
class CreateYourSourceCommand implements CreateSourceCommandInterface
159+
{
160+
/**
161+
* @JMS\Type("Ergonode\SharedKernel\Domain\Aggregate\SourceId")
162+
*/
163+
private SourceId $id;
164+
165+
/**
166+
* @JMS\Type("string")
167+
*/
168+
private string $name;
169+
170+
public function __construct(
171+
SourceId $id,
172+
string $name
173+
) {
174+
$this->id = $id;
175+
$this->name = $name;
176+
}
177+
178+
public function getId(): SourceId
179+
{
180+
return $this->id;
181+
}
182+
183+
public function getName(): string
184+
{
185+
return $this->name;
186+
}
187+
}
188+
189+
```
190+
191+
```php
192+
namespace YourNameSpace\Infrastructure\Handler;
193+
194+
use Ergonode\Importer\Domain\Repository\SourceRepositoryInterface;
195+
use YourNameSpace\Domain\Command\CreateYourSourceCommand;
196+
use YourNameSpace\Domain\Entity\YourSource;
197+
198+
class YourSourceSourceCommandHandler
199+
{
200+
private SourceRepositoryInterface $repository;
201+
202+
public function __construct(SourceRepositoryInterface $repository)
203+
{
204+
$this->repository = $repository;
205+
}
206+
207+
/**
208+
* @throws \Exception
209+
*/
210+
public function __invoke(CreateYourSourceCommand $command): void
211+
{
212+
$source = new YourSource(
213+
$command->getId(),
214+
$command->getName()
215+
);
216+
217+
$this->repository->save($source);
218+
}
219+
}
220+
221+
```
222+
223+
At last add you source import processor.
224+
225+
```php
226+
namespace YourNameSpace\Infrastructure\Processor;
227+
228+
use Ergonode\Importer\Domain\Entity\Import;
229+
use Ergonode\Importer\Infrastructure\Processor\SourceImportProcessorInterface;
230+
use YourNameSpace\Domain\Entity\YourSource;
231+
232+
class YourSourceImportProcess implements SourceImportProcessorInterface
233+
{
234+
public function supported(string $type): bool
235+
{
236+
return $type === YourSource::TYPE;
237+
}
238+
239+
public function start(Import $import): void
240+
{
241+
// here is body of your import process
242+
}
243+
}
244+
```

docs/backend/modules/importer.md

Lines changed: 13 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -5,46 +5,26 @@
55
This module is responsible for managing imports to ergonode from external systems or files.
66

77

8-
## Reader
8+
## Custom Import error
99

10-
**Reader** is a component responsible for reading files in different formats.
10+
If an error occurs during the import process, we may want to inform the user by presenting the relevant content in the import error list.
1111

12-
One Reader class is responsible for one file type.
13-
14-
To use it you need to create a class which implements **FileReaderInterface**.
12+
For that we need to create custom error. We're doing that by creating new exception class extended from ```Ergonode\Importer\Infrastructure\Exception\ImportException```
1513

1614
```php
17-
<?php
18-
namespace Ergonode\Component\Importer\Infrastructure\Reader;
15+
namespace YourNameSpace\Infrastructure\Exception;
1916

20-
interface FileReaderInterface extends \IteratorAggregate, \Countable
17+
class YourCustomException extends ImportException
2118
{
22-
public function open(string $file, array $configuration = [], array $formatters = []): void;
23-
public function read(): \Traversable;
24-
public function close(): void;
25-
}
26-
27-
```
28-
29-
Example of **Reader** you can find here:
30-
`Ergonode\Component\Importer\Infrastructure\Reader\CsvFileReader.php`
31-
32-
33-
## Formatter
19+
private const MESSAGE = 'Your error message with param {param}';
3420

35-
**Formatters** are objects responsbile for changing every line from input file.
36-
37-
One **Formatter** class is responsible for one text editing operation. For example it can be used for removing some unwanted characters or changing text encoding.
38-
39-
You you need to create a class which implements **FormatterInterface**.
40-
41-
```php
42-
<?php
43-
namespace Ergonode\Component\Importer\Infrastructure\Formatter;
44-
45-
interface FormatterInterface
46-
{
47-
public function format(string $string): string;
21+
public function __construct(string $param, \Throwable $previous = null)
22+
{
23+
parent::__construct(self::MESSAGE, ['{param}' => $param], $previous);
24+
}
4825
}
4926
```
5027

28+
In addition to the importer.yml translation file, we can add a location-based version of our message
29+
30+
Now if you throw this exception in import process, message will be automatically added to import error list

docs/frontend/architecture/app-structure.md

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -75,9 +75,6 @@ Ergonode in the **developer version** contains in its structure the most importa
7575
* **router.js** <br>
7676
[Vue router][vue-router] configuration file.
7777
> The default file is extended with additional configurations from the [VueMS library][vuems]
78-
* **router.local.js** <br>
79-
Local routing file if needed.
80-
> A better idea would be to use modules and set routing there or extend the existing routing.
8178
* **.env.dist** <br>
8279
Example file with environmental variables - need to copy and create your own `.env` file.
8380
* **babel.config.js** <br>

0 commit comments

Comments
 (0)