many small fixes

This commit is contained in:
Dennis Eichhorn 2023-02-10 18:20:57 +01:00
parent 1f9bdeb09e
commit b547df29a6
16 changed files with 533 additions and 285 deletions

1
.gitignore vendored
View File

@ -1 +1,2 @@
vendor
Definitions

View File

@ -8,7 +8,7 @@
"uri": "{/lang}/{/app}/workflow/instance/list?{?}",
"target": "self",
"icon": null,
"order": 40,
"order": 90,
"from": "Workflow",
"permission": { "permission": 2, "category": null, "element": null },
"parent": 1003301001,

View File

@ -173,190 +173,275 @@
}
]
}
}
},
"1005500002": {
"name": "Adapter",
"description": {
"en": "Takes input data and forwards the data to another action. Check the outputs and inputs of the actions to create the correct mapping.",
"de": "Übernimmt Eingangsdaten und leitet diese an eine andere Aktion weiter. Überprüfe die Ausgaben und Eingaben der jeweiligen Aktionen um die korrekten Verknüpfungen zu erstellen."
},
"1005500002": {
"name": "Adapter",
"description": {
"en": "Takes input data and forwards the data to another action. Check the outputs and inputs of the actions to create the correct mapping.",
"de": "Übernimmt Eingangsdaten und leitet diese an eine andere Aktion weiter. Überprüfe die Ausgaben und Eingaben der jeweiligen Aktionen um die korrekten Verknüpfungen zu erstellen."
},
"function_type": "API",
"function": "apiAdapter",
"inputs": [
"map",
"{*}"
],
"outputs": [
"{*}"
],
"settings": {
"map": {
"type": "textarea",
"subtype": null,
"default": null,
"pattern": null,
"examples": [
"output1 -> input1\noutput1.name -> input2"
],
"required": true,
"title": {
"en": "Adapter",
"de": "Adapter"
},
"description": {
"en": "",
"de": ""
}
"function_type": "API",
"function": "apiAdapter",
"inputs": [
"map",
"{*}"
],
"outputs": [
"{*}"
],
"settings": {
"map": {
"type": "textarea",
"subtype": null,
"default": null,
"pattern": null,
"examples": [
"output1 -> input1\noutput1.name -> input2"
],
"required": true,
"title": {
"en": "Adapter",
"de": "Adapter"
},
"description": {
"en": "",
"de": ""
}
}
}
},
"1005500003": {
"name": "Listen Trigger",
"description": {
"en": "Listens to trigger",
"de": "Wartet auf Trigger"
},
"1005500003": {
"name": "Listen Trigger",
"description": {
"en": "Listens to trigger",
"de": "Wartet auf Trigger"
},
"function_type": "API",
"function": "apiListenToTrigger",
"inputs": [
"type",
"trigger",
"delete",
"{*}"
],
"outputs": [
"{*}"
],
"settings": {
"type": {
"type": "select",
"subtype": null,
"default": "1",
"pattern": null,
"examples": [],
"required": true,
"title": {
"en": "Type",
"de": "Type"
},
"options": [
{
"value": "1",
"text": {
"en": "Existing Trigger",
"de": "Bestehender Trigger"
}
},
{
"value": "2",
"text": {
"en": "New Trigger",
"de": "Neuer Trigger"
}
"function_type": "API",
"function": "apiListenToTrigger",
"inputs": [
"type",
"trigger",
"delete",
"{*}"
],
"outputs": [
"{*}"
],
"settings": {
"type": {
"type": "select",
"subtype": null,
"default": "1",
"pattern": null,
"examples": [],
"required": true,
"title": {
"en": "Type",
"de": "Type"
},
"options": [
{
"value": "1",
"text": {
"en": "Existing Trigger",
"de": "Bestehender Trigger"
}
],
"description": {
"en": "",
"de": ""
}
},
"trigger": {
"type": "input",
"subtype": "text",
"default": null,
"pattern": null,
"examples": [
"PRE:Module:Billing:bill-create",
"PRE:Module:Billing:bill-update.*",
"PRE:Module:Billing:bill-update-{$id}"
],
"required": true,
"title": {
"en": "Trigger",
"de": "Trigger"
},
"description": {
"en": "",
"de": ""
}
},
"delete": {
"type": "select",
"subtype": null,
"default": "1",
"pattern": null,
"examples": [],
"required": true,
"title": {
"en": "Type",
"de": "Type"
},
"options": [
{
"value": "1",
"text": {
"en": "Never",
"de": "Niemals"
}
},
{
"value": "2",
"text": {
"en": "After trigger execution",
"de": "Nach Triggerausführung"
}
},
{
"value": "3",
"text": {
"en": "After workflow execution",
"de": "Nach Workflowausführung"
}
{
"value": "2",
"text": {
"en": "New Trigger",
"de": "Neuer Trigger"
}
],
"description": {
"en": "",
"de": ""
}
},
}
},
"1005500004": {
"name": "Run Trigger",
"description": {
"en": "Takes input data and forwards the data to another action. Check the outputs and inputs of the actions to create the correct mapping.",
"de": "Übernimmt Eingangsdaten und leitet diese an eine andere Aktion weiter. Überprüfe die Ausgaben und Eingaben der jeweiligen Aktionen um die korrekten Verknüpfungen zu erstellen."
],
"description": {
"en": "",
"de": ""
}
},
"function_type": "API",
"function": "apiAdapter",
"inputs": [
"map",
"{*}"
],
"outputs": [
"{*}"
],
"settings": {
"map": {
"type": "textarea",
"subtype": null,
"default": null,
"pattern": null,
"examples": [
"output1 -> input1\noutput1.name -> input2"
],
"required": true,
"title": {
"en": "Adapter",
"de": "Adapter"
"trigger": {
"type": "input",
"subtype": "text",
"default": null,
"pattern": null,
"examples": [
"PRE:Module:Billing:bill-create",
"PRE:Module:Billing:bill-update.*",
"PRE:Module:Billing:bill-update-{$id}"
],
"required": true,
"title": {
"en": "Trigger",
"de": "Trigger"
},
"description": {
"en": "",
"de": ""
}
},
"delete": {
"type": "select",
"subtype": null,
"default": "1",
"pattern": null,
"examples": [],
"required": true,
"title": {
"en": "Type",
"de": "Type"
},
"options": [
{
"value": "1",
"text": {
"en": "Never",
"de": "Niemals"
}
},
"description": {
"en": "",
"de": ""
{
"value": "2",
"text": {
"en": "After trigger execution",
"de": "Nach Triggerausführung"
}
},
{
"value": "3",
"text": {
"en": "After workflow execution",
"de": "Nach Workflowausführung"
}
}
],
"description": {
"en": "",
"de": ""
}
}
}
},
"1005500004": {
"name": "Run Trigger",
"description": {
"en": "Takes input data and forwards the data to another action. Check the outputs and inputs of the actions to create the correct mapping.",
"de": "Übernimmt Eingangsdaten und leitet diese an eine andere Aktion weiter. Überprüfe die Ausgaben und Eingaben der jeweiligen Aktionen um die korrekten Verknüpfungen zu erstellen."
},
"function_type": "API",
"function": "apiRun",
"inputs": [
"map",
"{*}"
],
"outputs": [
"{*}"
],
"settings": {
"map": {
"type": "textarea",
"subtype": null,
"default": null,
"pattern": null,
"examples": [
"output1 -> input1\noutput1.name -> input2"
],
"required": true,
"title": {
"en": "Adapter",
"de": "Adapter"
},
"description": {
"en": "",
"de": ""
}
}
}
},
"1005500005": {
"name": "Timed Trigger",
"description": {
"en": "Timed trigger",
"de": "Wartet auf Trigger"
},
"function_type": "API",
"function": "apiRun",
"inputs": [
"interval",
"{*}"
],
"outputs": [
"{*}"
],
"settings": {
"interval": {
"type": "input",
"subtype": "text",
"default": null,
"pattern": null,
"examples": [],
"required": true,
"title": {
"en": "Interval",
"de": "Interval"
},
"description": {
"en": "",
"de": ""
}
}
}
},
"1005500006": {
"name": "Cli Action",
"description": {
"en": "Cli action",
"de": "Konsolenbefehl"
},
"function_type": "API",
"function": "apiRun",
"inputs": [
"cmd",
"{*}"
],
"outputs": [
"{*}"
],
"settings": {
"cmd": {
"type": "input",
"subtype": "text",
"default": null,
"pattern": null,
"examples": [],
"required": true,
"title": {
"en": "Command",
"de": "Befehl"
},
"description": {
"en": "",
"de": ""
}
}
}
},
"1005500007": {
"name": "Workflow Script",
"description": {
"en": "Workflow script",
"de": "Workflow Script"
},
"function_type": "API",
"function": "apiRun",
"inputs": [
"{*}"
],
"outputs": [
"{*}"
],
"settings": {
}
}
}
}

View File

@ -32,10 +32,17 @@
"default": null,
"null": true
},
"workflow_template_schema": {
"name": "workflow_template_schema",
"type": "TEXT",
"default": null,
"null": true
},
"workflow_template_media": {
"name": "workflow_template_media",
"type": "INT",
"null": false,
"null": true,
"default": null,
"foreignTable": "media",
"foreignKey": "media_id"
},

View File

@ -69,6 +69,13 @@ final class Installer extends InstallerAbstract
\mkdir(__DIR__ . '/../../../temp');
}
if (!\is_dir(__DIR__ . '/../Definitions')) {
\mkdir(__DIR__ . '/../Definitions');
\file_put_contents(__DIR__ . '/../Definitions/actions.json', '[]');
\file_put_contents(__DIR__ . '/../Definitions/triggers.json', '[]');
}
$apiApp = new class() extends ApplicationAbstract
{
protected string $appName = 'Api';
@ -81,13 +88,76 @@ final class Installer extends InstallerAbstract
$apiApp->moduleManager = $app->moduleManager;
$apiApp->eventManager = $app->eventManager;
foreach ($workflowData as $workflow) {
self::installWorkflow($apiApp, $workflow);
}
self::createTriggers($apiApp, $workflowData['triggers'] ?? []);
self::createActions($apiApp, $workflowData['actions'] ?? []);
return [];
}
/**
* Install trigger.
*
* @param ApplicationAbstract $app Application
* @param array $data Additional data
*
* @return void
*
* @since 1.0.0
*/
private static function createTriggers(ApplicationAbstract $app, array $data) : void
{
$path = __DIR__ . '/../Definitions/triggers.json';
if (!\is_file($path)) {
return;
}
$installed = \file_get_contents($path);
if ($installed === false) {
return;
}
$installedData = \json_decode($installed, true);
if ($installedData === false) {
return;
}
$new = $installedData + $data;
\file_put_contents($path, \json_encode($new));
}
/**
* Install action.
*
* @param ApplicationAbstract $app Application
* @param array $data Additional data
*
* @return void
*
* @since 1.0.0
*/
private static function createActions(ApplicationAbstract $app, array $data) : void
{
$path = __DIR__ . '/../Definitions/actions.json';
if (!\is_file($path)) {
return;
}
$installed = \file_get_contents($path);
if ($installed === false) {
return;
}
$installedData = \json_decode($installed, true);
if ($installedData === false) {
return;
}
$new = $installedData + $data;
\file_put_contents($path, \json_encode($new));
}
/**
* Install application page.
*

View File

@ -423,72 +423,92 @@ final class ApiController extends Controller
return;
}
$path = '/Modules/Workflow/' . $request->getData('name');
$collectionId = 0;
$uploaded = [];
/** @var \Modules\Media\Models\Media[] $uploaded */
$uploaded = $this->app->moduleManager->get('Media')->uploadFiles(
$request->getDataList('names'),
$request->getDataList('filenames'),
$uploadedFiles,
$request->header->account,
__DIR__ . '/../../../Modules/Media/Files' . $path,
$path,
pathSettings: PathSettings::FILE_PATH
);
if ($request->hasFiles()) {
$path = '/Modules/Workflow/' . $request->getData('name');
foreach ($uploaded as $upload) {
if ($upload instanceof NullMedia) {
continue;
/** @var \Modules\Media\Models\Media[] $uploaded */
$uploaded = $this->app->moduleManager->get('Media')->uploadFiles(
names: $request->getDataList('names'),
fileNames: $request->getDataList('filenames'),
files: $uploadedFiles,
account: $request->header->account,
basePath: __DIR__ . '/../../../Modules/Media/Files' . $path,
virtualPath: $path,
pathSettings: PathSettings::FILE_PATH
);
foreach ($uploaded as $upload) {
if ($upload instanceof NullMedia) {
continue;
}
$files[] = $upload;
}
$files[] = $upload;
/** @var \Modules\Media\Models\Collection $collection */
$collection = $this->app->moduleManager->get('Media')->createMediaCollectionFromMedia(
(string) ($request->getData('name') ?? ''),
(string) ($request->getData('description') ?? ''),
$files,
$request->header->account
);
if ($collection instanceof NullCollection) {
$response->header->status = RequestStatusCode::R_403;
$this->fillJsonResponse($request, $response, NotificationLevel::ERROR, 'Template', 'Couldn\'t create collection for template', null);
return;
}
$collection->setPath('/Modules/Media/Files/Modules/Workflow/' . ((string) ($request->getData('name') ?? '')));
$collection->setVirtualPath('/Modules/Workflow');
$this->createModel($request->header->account, $collection, CollectionMapper::class, 'collection', $request->getOrigin());
$collectionId = $collection->getId();
}
/** @var \Modules\Media\Models\Collection $collection */
$collection = $this->app->moduleManager->get('Media')->createMediaCollectionFromMedia(
(string) ($request->getData('name') ?? ''),
(string) ($request->getData('description') ?? ''),
$files,
$request->header->account
);
if ($collection instanceof NullCollection) {
$response->header->status = RequestStatusCode::R_403;
$this->fillJsonResponse($request, $response, NotificationLevel::ERROR, 'Template', 'Couldn\'t create collection for template', null);
return;
}
$collection->setPath('/Modules/Media/Files/Modules/Workflow/' . ((string) ($request->getData('name') ?? '')));
$collection->setVirtualPath('/Modules/Workflow');
CollectionMapper::create()->execute($collection);
$template = $this->createTemplateFromRequest($request, $collection->getId());
$template = $this->createTemplateFromRequest($request, $collectionId);
$this->createModel($request->header->account, $template, WorkflowTemplateMapper::class, 'workflow_template', $request->getOrigin());
// replace placeholders
foreach ($uploaded as $upload) {
if ($upload instanceof NullMedia) {
continue;
if ($collectionId > 0) {
foreach ($uploaded as $upload) {
if ($upload instanceof NullMedia) {
continue;
}
$path = $upload->getAbsolutePath();
$content = \file_get_contents($path);
if ($content === false) {
$content = '';
}
$content = $this->parseKeys($content, $template);
\file_put_contents($path, $content);
}
$path = $upload->getAbsolutePath();
$content = \file_get_contents($path);
if ($content === false) {
$content = '';
}
$content = \str_replace('{workflow_id}', (string) $template->getId(), $content);
\file_put_contents($path, $content);
$this->createDatabaseForTemplate($template);
}
$this->createDatabaseForTemplate($template);
$this->fillJsonResponse($request, $response, NotificationLevel::OK, 'Template', 'Template successfully created', $template);
}
private function parseKeys(string $content, WorkflowTemplate $template) : string
{
if ($content === '') {
return '';
}
$content = \str_replace('{workflow_id}', (string) $template->getId(), $content);
return $content;
}
/**
* Validate template create request
*
@ -501,9 +521,7 @@ final class ApiController extends Controller
private function validateTemplateCreate(RequestAbstract $request) : array
{
$val = [];
if (($val['name'] = empty($request->getData('name')))
|| ($val['files'] = empty($request->getFiles()))
) {
if (($val['name'] = empty($request->getData('name')))) {
return $val;
}
@ -525,6 +543,7 @@ final class ApiController extends Controller
$workflowTemplate->name = (string) ($request->getData('name') ?? '');
$workflowTemplate->description = Markdown::parse((string) ($request->getData('description') ?? ''));
$workflowTemplate->descriptionRaw = (string) ($request->getData('description') ?? '');
$workflowTemplate->schema = $request->getDataJson('schema');
if ($collectionId > 0) {
$workflowTemplate->source = new NullCollection($collectionId);
@ -554,15 +573,15 @@ final class ApiController extends Controller
$files = $collection->getSources();
foreach ($files as $file) {
if (!StringUtils::endsWith($file->getPath(), 'db.json')) {
if (!StringUtils::endsWith($file->getAbsolutePath(), 'db.json')) {
continue;
}
if (!\is_file($file->getPath())) {
if (!\is_file($file->getAbsolutePath())) {
return;
}
$content = \file_get_contents($file->getPath());
$content = \file_get_contents($file->getAbsolutePath());
if ($content === false) {
return; // @codeCoverageIgnore
}
@ -653,6 +672,8 @@ final class ApiController extends Controller
{
$controller = null;
// @todo: implement default workflow instance;
$file = $template->source->findFile('WorkflowController.php');
require_once $file->getAbsolutePath();

View File

@ -107,7 +107,7 @@ final class BackendController extends Controller
$controller = new \Modules\Workflow\Controller\WorkflowController($this->app, $template);
$controller->createTemplateViewFromRequest($view, $request, $response);
} else {
$view->setTemplate('/Modules/Workflow/Theme/Backend/workflow-profile');
$view->setTemplate('/Modules/Workflow/Theme/Backend/workflow-template');
}
$head = $response->get('Content')->getData('head');

View File

@ -6,15 +6,16 @@ Creating:
```mermaid
graph TD;
CREATE_TEMPLATE((Create))-->REGISTER_TRIGGER[Register template trigger]
REGISTER_TRIGGER-->HAS_OTHER_TRIGGER{Has other trigger}
HAS_OTHER_TRIGGER--YES-->REGISTER_TRIGGER_2[Register existing trigger]
REGISTER_TRIGGER-->CHECK_TYPE{Check type}
CHECK_TYPE--LISTENER-->REGISTER_TRIGGER_2[Register existing trigger]
CHECK_TYPE--TIMED-->REGISTER_CRON[Register cron job]
```
Running:
```mermaid
graph TD;
MAIN_TRIGGER((Trigger))-->CREATE_INSTANCE[Create Instance in DB]
MAIN_TRIGGER((Trigger\nAction, Manual, Time))-->CREATE_INSTANCE[Create Instance in DB]
MAIN_TRIGGER-->HAS_SUB_TRIGGERS{Has Sub Triggers}
HAS_SUB_TRIGGERS--YES-->REGISTER_TRIGGER[Register sub triggers]
MAIN_TRIGGER-->RUN_CODE_1[Run Code]
@ -43,5 +44,3 @@ Billing:
3. Is successful
1. yes: send email
2. no: inform sales person + deactivate benefits

View File

@ -37,6 +37,7 @@ final class WorkflowInstanceAbstractMapper extends DataMapperFactory
'workflow_instance_id' => ['name' => 'workflow_instance_id', 'type' => 'int', 'internal' => 'id'],
'workflow_instance_title' => ['name' => 'workflow_instance_title', 'type' => 'string', 'internal' => 'title'],
'workflow_instance_status' => ['name' => 'workflow_instance_status', 'type' => 'int', 'internal' => 'status'],
'workflow_instance_data' => ['name' => 'workflow_instance_data', 'type' => 'string', 'internal' => 'data'],
'workflow_instance_template' => ['name' => 'workflow_instance_template', 'type' => 'int', 'internal' => 'template'],
'workflow_instance_created_at' => ['name' => 'workflow_instance_created_at', 'type' => 'DateTimeImmutable', 'internal' => 'createdAt', 'readonly' => true],
'workflow_instance_created_by' => ['name' => 'workflow_instance_created_by', 'type' => 'int', 'internal' => 'createdBy', 'readonly' => true],

View File

@ -93,6 +93,8 @@ class WorkflowTemplate
*/
public Collection $source;
public array $schema = [];
/**
* Constructor.
*

View File

@ -40,6 +40,7 @@ final class WorkflowTemplateMapper extends DataMapperFactory
'workflow_template_name' => ['name' => 'workflow_template_name', 'type' => 'string', 'internal' => 'name'],
'workflow_template_desc' => ['name' => 'workflow_template_desc', 'type' => 'string', 'internal' => 'description'],
'workflow_template_descRaw' => ['name' => 'workflow_template_descRaw', 'type' => 'string', 'internal' => 'descriptionRaw'],
'workflow_template_schema' => ['name' => 'workflow_template_schema', 'type' => 'Json', 'internal' => 'schema'],
'workflow_template_media' => ['name' => 'workflow_template_media', 'type' => 'int', 'internal' => 'source'],
'workflow_template_created_at' => ['name' => 'workflow_template_created_at', 'type' => 'DateTimeImmutable', 'internal' => 'createdAt', 'readonly' => true],
'workflow_template_created_by' => ['name' => 'workflow_template_created_by', 'type' => 'int', 'internal' => 'createdBy', 'readonly' => true],

View File

@ -22,7 +22,7 @@ echo $this->getData('nav')->render(); ?>
<div class="row">
<div class="col-xs-12">
<div class="portlet">
<div class="portlet-head"><?= $this->getHtml('instance'); ?><i class="fa fa-download floatRight download btn"></i></div>
<div class="portlet-head"><?= $this->getHtml('Instances'); ?><i class="fa fa-download floatRight download btn"></i></div>
<table class="default">
<thead>
<td><?= $this->getHtml('Status'); ?>

View File

@ -22,7 +22,7 @@ echo $this->getData('nav')->render(); ?>
<div class="row">
<div class="col-xs-12">
<div class="portlet">
<div class="portlet-head"><?= $this->getHtml('instance'); ?><i class="fa fa-download floatRight download btn"></i></div>
<div class="portlet-head"><?= $this->getHtml('Instances'); ?><i class="fa fa-download floatRight download btn"></i></div>
<table class="default">
<thead>
<td><?= $this->getHtml('Status'); ?>

View File

@ -33,38 +33,6 @@ $previous = empty($templates) ? 'workflow/template/list' : '{/lang}/{/app}/workf
$next = empty($templates) ? 'workflow/template/list' : '{/lang}/{/app}/workflow/template/list?{?}&id=' . \end($templates)->getId() . '&ptype=n';
echo $this->getData('nav')->render(); ?>
<div class="row">
<div class="col-xs-12">
<div class="box">
<ul class="crumbs-2">
<li data-href="<?= UriFactory::build('{/lang}/{/app}/workflow/template/list?path=/Accounts/' . $accountDir); ?>"><a href="<?= UriFactory::build('{/lang}/{/app}/workflow/template/list?path=/Accounts/' . $accountDir); ?>"><i class="fa fa-home"></i></a>
<li data-href="<?= UriFactory::build('{/lang}/{/app}/workflow/template/list?path=/'); ?>"><a href="<?= UriFactory::build('{/lang}/{/app}/workflow/template/list?path=/'); ?>">/</a></li>
<?php
$subPath = '';
$paths = \explode('/', \ltrim($mediaPath, '/'));
$length = \count($paths);
$parentPath = '';
for ($i = 0; $i < $length; ++$i) :
if ($paths[$i] === '') {
continue;
}
if ($i === $length - 1) {
$parentPath = $subPath === '' ? '/' : $subPath;
}
$subPath .= '/' . $paths[$i];
$url = UriFactory::build('{/lang}/{/app}/workflow/template/list?path=' . $subPath);
?>
<li data-href="<?= $url; ?>"<?= $i === $length - 1 ? 'class="active"' : ''; ?>><a href="<?= $url; ?>"><?= $this->printHtml($paths[$i]); ?></a></li>
<?php endfor; ?>
</ul>
</div>
</div>
</div>
<div class="row">
<div class="col-xs-12">
<div class="portlet">
@ -125,20 +93,7 @@ echo $this->getData('nav')->render(); ?>
<td>
<td>
<?php endif; ?>
<?php $count = 0; foreach ($collections as $key => $value) : ++$count;
$url = UriFactory::build('{/lang}/{/app}/workflow/template/list?path=' . \rtrim($value->getVirtualPath(), '/') . '/' . $value->name);
?>
<tr data-href="<?= $url; ?>">
<td><label class="checkbox" for="workflowTemplateList-<?= $key; ?>">
<input type="checkbox" id="workflowTemplateList-<?= $key; ?>" name="templateselect">
<span class="checkmark"></span>
</label>
<td><a href="<?= $url; ?>"><i class="fa fa-folder-open-o"></i></a>
<td><a href="<?= $url; ?>"><?= $this->printHtml($value->name); ?></a>
<td><a class="content" href="<?= UriFactory::build('{/lang}/{/app}/profile/single?{?}&for=' . $value->createdBy->getId()); ?>"><?= $this->printHtml($this->renderUserName('%3$s %2$s %1$s', [$value->createdBy->name1, $value->createdBy->name2, $value->createdBy->name3, $value->createdBy->login ?? ''])); ?></a>
<td><a href="<?= $url; ?>"><?= $this->printHtml($value->createdAt->format('Y-m-d')); ?></a>
<?php endforeach; ?>
<?php foreach ($templates as $key => $template) : ++$count;
<?php $count = 0; foreach ($templates as $key => $template) : ++$count;
$url = UriFactory::build('{/lang}/{/app}/workflow/template/profile?{?}&id=' . $template->getId()); ?>
<tr tabindex="0" data-href="<?= $url; ?>">
<td><label class="checkbox" for="workflowTemplateList-<?= $key; ?>">

View File

@ -0,0 +1,105 @@
<?php
/**
* Karaka
*
* PHP Version 8.1
*
* @package Modules\Workflow
* @copyright Dennis Eichhorn
* @license OMS License 1.0
* @version 1.0.0
* @link https://jingga.app
*/
declare(strict_types=1);
use phpOMS\Uri\UriFactory;
use phpOMS\Views\View;
/**
* @var \phpOMS\Views\View $this
* @var \Modules\Workflow\Models\Template $template
*/
$template = $this->getData('template');
$actions = \json_decode(\file_get_contents(__DIR__ . '/../../Definitions/actions.json'), true);
function renderLeaf(array $leaf, string $parent = null)
{
$boxes = [
'first' => ['((', '))'],
'standard' => ['[', ']'],
'if' => ['{', '}']
];
foreach ($leaf as $key => $e) {
$type = $e['id'] === '1005500001'
? 'if'
: 'standard';
if ($parent !== null) {
echo ' ' . $parent . '-->' . $parent . ':' . $key . ':' . $e['id'] . $boxes[$type][0] . $e['id'] . $boxes[$type][1] . ";\n";
} else {
echo ' ' . $key . ':' . $e['id'] . $boxes['first'][0] . $e['id'] . $boxes['first'][1] . ";\n";
}
renderLeaf($e['children'], ($parent === null ? '' : $parent . ':') . $key . ':' . $e['id']);
}
}
function renderElements(array $leaf, array $actions)
{
foreach ($leaf as $e) {
$name = View::html($actions[(int) $e['id']]['name']);
echo <<<NEWDOC
<section class="portlet">
<div class="portlet-body">{$name}</div>
<div class="portlet-body"></div>
</section>
NEWDOC;
renderElements($e['children'], $actions);
}
}
echo $this->getData('nav')->render(); ?>
<?php
if (!empty($template->schema)) :
$level = $template->schema;
?>
<div class="row">
<div class="col-md-6 col-xs-12">
<section class="portlet sticky">
<div class="portlet-head"><?= $this->getHtml('Workflow'); ?></div>
<div class="portlet-body">
<div class="mermaid">
graph TD;
<?php renderLeaf($level, null); ?>
</div>
</div>
</section>
</div>
<div class="col-md-3 col-xs-12">
<section class="portlet">
<div class="portlet-head"><?= $this->getHtml('Active'); ?></div>
</section>
<?php renderElements($level, $actions); ?>
</div>
<div class="col-md-3 col-xs-12">
<section class="portlet">
<div class="portlet-head"><?= $this->getHtml('Available'); ?></div>
</section>
<?php foreach ($actions as $action) : ?>
<section class="portlet">
<div class="portlet-body"><?= $this->printHtml($action['name']); ?></div>
<div class="portlet-body"><?= $this->printHtml($action['description'][$this->request->getLanguage()]); ?></div>
</section>
<?php endforeach; ?>
</div>
</div>
<?php endif; ?>

View File

@ -23,7 +23,8 @@
"Media": "1.0.0"
},
"providing": {
"Navigation": "*"
"Navigation": "*",
"Media": "*"
},
"load": [
{