diff --git a/ProcessMaker/Bpmn/MustacheOptions.php b/ProcessMaker/Bpmn/MustacheOptions.php
index 846ba30195..a3d0507b0c 100644
--- a/ProcessMaker/Bpmn/MustacheOptions.php
+++ b/ProcessMaker/Bpmn/MustacheOptions.php
@@ -18,36 +18,76 @@ public function __construct()
'json' => [$this, 'json'],
'serialize' => [$this, 'serialize'],
'xml' => [$this, 'xml'],
+ 'urlencode' => [$this, 'urlencode'],
];
}
- public function html64($text, Mustache_LambdaHelper $helper)
+ public function html64($text, ?Mustache_LambdaHelper $helper = null)
{
+ if (!$helper) {
+ // Support for PRAGMA_FILTERS
+ return base64_encode('
' . $text . '');
+ }
return base64_encode('' . $helper->render($text) . '');
}
- public function base64($text, Mustache_LambdaHelper $helper)
+ public function base64($text, ?Mustache_LambdaHelper $helper = null)
{
+ if (!$helper) {
+ // Support for PRAGMA_FILTERS
+ return base64_encode($text);
+ }
return base64_encode($helper->render($text));
}
- public function key($text, Mustache_LambdaHelper $helper)
+ public function key($text, ?Mustache_LambdaHelper $helper = null)
{
+ if (!$helper) {
+ // Support for PRAGMA_FILTERS
+ return urlencode(Hash::make($text));
+ }
return urlencode(Hash::make($helper->render($text)));
}
- public function json($text, Mustache_LambdaHelper $helper)
+ public function json($text, ?Mustache_LambdaHelper $helper = null)
{
+ if (!$helper) {
+ // Support for PRAGMA_FILTERS
+ return json_encode($text);
+ }
return json_encode($helper->render($text));
}
- public function serialize($text, Mustache_LambdaHelper $helper)
+ public function serialize($text, ?Mustache_LambdaHelper $helper = null)
{
+ if (!$helper) {
+ // Support for PRAGMA_FILTERS
+ return serialize($text);
+ }
return serialize($helper->render($text));
}
- public function xml($text, Mustache_LambdaHelper $helper)
+ public function xml($text, ?Mustache_LambdaHelper $helper = null)
{
+ if (!$helper) {
+ // Support for PRAGMA_FILTERS
+ return xmlrpc_encode($text);
+ }
return xmlrpc_encode($helper->render($text));
}
+
+ /**
+ * URL encode a string
+ *
+ * @param string $text
+ * @param Mustache_LambdaHelper|null $helper
+ * @return string
+ */
+ public function urlencode($text, ?Mustache_LambdaHelper $helper = null)
+ {
+ if (!$helper) {
+ return urlencode($text);
+ }
+ return urlencode($helper->render($text));
+ }
}
diff --git a/ProcessMaker/Console/Commands/Api2TypescriptCommand.php b/ProcessMaker/Console/Commands/Api2TypescriptCommand.php
new file mode 100644
index 0000000000..9a46e98138
--- /dev/null
+++ b/ProcessMaker/Console/Commands/Api2TypescriptCommand.php
@@ -0,0 +1,950 @@
+files = $files;
+ }
+
+ /**
+ * Execute the console command.
+ *
+ * @return int
+ */
+ public function handle()
+ {
+ $outputDirectory = $this->argument('output');
+
+ // update the api-docs.json file
+ Artisan::call('l5-swagger:generate');
+
+ // Parse JSON file
+ $openapi = $this->parseJsonFile();
+ if (!$openapi) {
+ $this->error("Failed to parse OpenAPI JSON file.");
+ return 1;
+ }
+ $this->openapi = $openapi;
+
+ // Create output directory if it doesn't exist
+ if (!$this->files->exists($outputDirectory)) {
+ $this->files->makeDirectory($outputDirectory, 0755, true);
+ }
+
+ // Create subdirectories
+ $typesDir = "$outputDirectory/types";
+ $apiDir = "$outputDirectory/api";
+ $composablesDir = "$outputDirectory/composables";
+
+ foreach ([$typesDir, $apiDir, $composablesDir] as $dir) {
+ if (!$this->files->exists($dir)) {
+ $this->files->makeDirectory($dir, 0755, true);
+ }
+ }
+
+ // Extract API info
+ $apiTitle = $openapi['info']['title'] ?? 'API';
+ $apiDescription = $openapi['info']['description'] ?? 'API Description';
+ $apiVersion = $openapi['info']['version'] ?? '1.0.0';
+
+ // Extract tag names
+ $tags = [];
+ foreach ($openapi['paths'] as $path => $methods) {
+ foreach ($methods as $method => $details) {
+ if (isset($details['tags']) && is_array($details['tags'])) {
+ foreach ($details['tags'] as $tag) {
+ $tags[$tag] = true;
+ }
+ }
+ }
+ }
+ $tags = array_keys($tags);
+ // sort tags alphabetically ascending
+ sort($tags, SORT_FLAG_CASE | SORT_STRING);
+
+ $this->generateTypesForTag($openapi, 'types', $typesDir);
+ // Process each tag as a separate API client
+ foreach ($tags as $tag) {
+ $this->generateApiClassForTag($openapi, $tag, $apiDir);
+ $this->generateComposableForTag($tag, $composablesDir);
+ }
+
+ // Generate index files
+ $this->generateIndexFiles($tags, $apiDir, $composablesDir, $typesDir, $outputDirectory);
+
+ $this->info("TypeScript SDK generated successfully in $outputDirectory");
+ return 0;
+ }
+
+ /**
+ * Parse a JSON file
+ */
+ protected function parseJsonFile()
+ {
+ $content = file_get_contents(storage_path('api-docs/api-docs.json'));
+ $data = json_decode($content, true);
+ if (json_last_error() !== JSON_ERROR_NONE) {
+ $this->error("JSON parse error: " . json_last_error_msg());
+ return null;
+ }
+
+ return $data;
+ }
+
+ /**
+ * Map OpenAPI type to TypeScript type
+ */
+ protected function mapSwaggerTypeToTypescript($type)
+ {
+ switch ($type) {
+ case 'integer':
+ return 'number';
+ case 'number':
+ return 'number';
+ case 'boolean':
+ return 'boolean';
+ case 'array':
+ return 'any[]';
+ case 'object':
+ return 'Record';
+ default:
+ return 'string';
+ }
+ }
+
+ /**
+ * Generate TypeScript interfaces for schemas related to a tag
+ */
+ protected function generateTypesForTag($openapi, $tag, $outputDir)
+ {
+ $tagLower = strtolower($tag);
+ $interfaces = [];
+ $queryParamInterfaces = [];
+
+ // Get all schemas from components
+ $schemas = $openapi['components']['schemas'] ?? [];
+
+ // Process paths to find related schemas and generate query param interfaces
+ foreach ($openapi['paths'] as $path => $methods) {
+ foreach ($methods as $method => $details) {
+ // Generate query param interfaces for GET methods
+ if (isset($details['parameters'])) {
+ $queryParamInterface = $this->generateQueryParamInterface($details['parameters'], $tagLower, $details['operationId']);
+ if ($queryParamInterface) {
+ $queryParamInterfaces[] = $queryParamInterface;
+ }
+ }
+
+ // Check request body schema reference
+ if (isset($details['requestBody']['content']['application/json']['schema']['$ref'])) {
+ $schemaRef = $details['requestBody']['content']['application/json']['schema']['$ref'];
+ $this->collectSchemaFromRef($schemaRef, $schemas);
+ }
+
+ // Generate response type for operationId
+ $responseSchema = $details['responses']['200']['content']['application/json']['schema'] ??
+ $details['responses']['201']['content']['application/json']['schema'] ?? null;
+ if ($responseSchema && isset($responseSchema['properties'])) {
+ $queryParamInterfaces[] = $this->generateResponseType($details['operationId'], $responseSchema, $tagLower);
+ }
+
+ // Check response schema references
+ foreach ($details['responses'] ?? [] as $response) {
+ if (isset($response['content']['application/json']['schema']['$ref'])) {
+ $schemaRef = $response['content']['application/json']['schema']['$ref'];
+ $this->collectSchemaFromRef($schemaRef, $schemas);
+ }
+
+ // Check for arrays with items having refs
+ if (isset($response['content']['application/json']['schema']['properties']['data']['items']['$ref'])) {
+ $schemaRef = $response['content']['application/json']['schema']['properties']['data']['items']['$ref'];
+ $this->collectSchemaFromRef($schemaRef, $schemas);
+ }
+ }
+ }
+ }
+
+ // Generate TypeScript interfaces from schemas
+ foreach ($schemas as $name => $schema) {
+ $interfaces[] = $this->generateInterface($name, $schema);
+ }
+
+ // Write interfaces to file
+ $data = [
+ 'interfaces' => array_filter($interfaces),
+ 'queryParamInterfaces' => array_filter($queryParamInterfaces),
+ ];
+
+ $content = Blade::render($this->getStub('types'), $data);
+ $this->files->put("$outputDir/types.ts", $content);
+ }
+
+ /**
+ * Generate TypeScript API class for a tag
+ */
+ protected function generateApiClassForTag($openapi, $tag, $outputDir)
+ {
+ $tagLower = lcfirst(Str::camel($tag));
+ $className = "ProcessMaker" . ucfirst($tagLower) . "Api";
+
+ // Import interfaces
+ $imports = [];
+
+ // Add query param interfaces to imports
+ foreach ($openapi['paths'] as $path => $methods) {
+ foreach ($methods as $method => $details) {
+ if (!isset($details['tags']) || !in_array($tag, $details['tags'])) {
+ continue;
+ }
+
+ $operationId = $details['operationId'] ?? '';
+ if ($operationId) {
+ if (isset($details['parameters'])) {
+ // Import the query param interface
+ $interfaceName = ucfirst($this->camelCase($operationId)) . "QueryParams";
+ $interfaceCode = $this->generateQueryParamInterface($details['parameters'], $tagLower, $details['operationId']);
+ if ($interfaceCode) {
+ $imports[] = $interfaceName;
+ }
+ }
+
+ // Import the paginated response type and its type
+ $reference = $this->getResponseReference($operationId, $details['responses']);
+ if ($reference) {
+ $imports[] = $reference;
+ }
+ }
+ }
+ }
+
+ // Generate methods for each path
+ $methods = [];
+ foreach ($openapi['paths'] as $path => $pathMethods) {
+ foreach ($pathMethods as $method => $details) {
+ // Skip if not related to current tag
+ if (!isset($details['tags']) || !in_array($tag, $details['tags'])) {
+ continue;
+ }
+
+ $operationId = $details['operationId'] ?? '';
+ if ($operationId) {
+ $methods[] = $this->generateMethod($method, $path, $details, $imports);
+ }
+ }
+ }
+
+ $imports = array_unique($imports);
+ // sort imports alphabetically ascending
+ sort($imports, SORT_FLAG_CASE | SORT_STRING);
+ // sort methods alphabetically ascending by methodName
+ usort($methods, function($a, $b) {
+ return strcasecmp($a['methodName'], $b['methodName']);
+ });
+ $data = [
+ 'tagLower' => $tagLower,
+ 'className' => $className,
+ 'imports' => $imports,
+ 'methods' => $methods,
+ 'helper' => $this,
+ ];
+
+ // Generate the api.ts file
+ $content = Blade::render($this->getStub('api'), $data);
+ $this->files->put("$outputDir/$tagLower.api.ts", $content);
+
+ // Generate the api.spec.ts file
+ $content = Blade::render($this->getStub('api-spec'), $data);
+ $this->files->put("$outputDir/$tagLower.api.spec.ts", $content);
+ }
+
+ public function mockResponse(array $method)
+ {
+ return $method['responseExample'];
+ }
+
+ public function mockParamsArray(array $method, bool $camelCase): array
+ {
+ $params = [];
+ // Add path parameters
+ foreach ($method['pathParams'] as $param) {
+ $key = Str::camel($param['name']);
+ $params[$key] = $this->mockValue($param);
+ }
+ // Add request body parameter for POST/PUT methods
+ if (!empty($method['requestBody'])) {
+ if (isset($method['requestBody']['content']['multipart/form-data']['schema'])) {
+ $params['$body'] = $this->mockFromSchema($method['requestBody']['content']['multipart/form-data']['schema']);
+ } elseif (isset($method['requestBody']['content']['application/json']['schema'])) {
+ $schema = $method['requestBody']['content']['application/json']['schema'];
+ $params['$body'] = $this->mockFromSchema($schema);
+ } else {
+ throw new Exception("Failed to mock request body for " . $method['operationId']);
+ }
+ } elseif ($method['httpMethod'] === 'post' || $method['httpMethod'] === 'put' || $method['httpMethod'] === 'patch') {
+ $params['$body'] = (object) [];
+ }
+ $queryParams = [];
+ foreach ($method['queryParams'] as $param) {
+ $key = $camelCase ? Str::camel($param['name']) : $param['name'];
+ if (isset($param['$ref'])) {
+ $queryParams[$key] = $this->mockValue($this->getSchemaByRef($param['$ref']));
+ } else {
+ $queryParams[$key] = $this->mockValue($param);
+ }
+ }
+ if (!empty($queryParams)) {
+ $params['$queryParams'] = $queryParams;
+ }
+ return $params;
+ }
+
+ public function mockParams(array $method)
+ {
+ $params = $this->mockParamsArray($method, true);
+ foreach ($params as $key => $value) {
+ $params[$key] = $this->json($value, 6);
+ }
+ return implode(', ', $params);
+ }
+
+ private function getSchemaByRef(string $ref)
+ {
+ $refs = str_replace('/', '.', substr($ref, 2));
+ return Arr::get($this->openapi, $refs, null);
+ }
+
+ public function mockUrl(array $method)
+ {
+ $params = $this->mockParamsArray($method, false);
+ // replace ${param} with the value
+ $path = $method['apiPath'];
+ foreach ($params as $key => $value) {
+ if (is_array($value) || is_object($value)) {
+ continue;
+ }
+ $path = str_replace('${' . $key . '}', urlencode($value), $path);
+ }
+ // Add the query params to the path from $queryParams
+ if (isset($params['$queryParams'])) {
+ $first = true;
+ foreach ($params['$queryParams'] as $key => $value) {
+ if (is_array($value)) {
+ $value = implode(',', $value);
+ }
+ if (is_object($value)) {
+ $value = json_encode($value);
+ }
+ $path .= ($first ? '?' : '&') . urlencode($key) . '=' . urlencode($value);
+ $first = false;
+ }
+ }
+ $arguments = "'{$path}'";
+ if (isset($params['$body'])) {
+ $arguments .= ", " . $this->json($params['$body'], 6);
+ }
+ return $arguments;
+ }
+
+ public function json($value, int $leftMargin = 0)
+ {
+ if ($leftMargin > 0) {
+ $json = json_encode($value, JSON_UNESCAPED_SLASHES | JSON_PRETTY_PRINT);
+ // change the indent to 2 spaces
+ $json = preg_replace_callback(
+ '/^(?: {4})+/m',
+ function($m) {
+ return str_repeat(' ', 2 * (strlen($m[0]) / 4));
+ },
+ $json
+ );
+ // add the left margin
+ $json = str_replace("\n", "\n" . str_repeat(' ', $leftMargin), $json);
+ return $json;
+ }
+ return json_encode($value, JSON_UNESCAPED_SLASHES);
+ }
+
+ private function getResponseReference(string $operationId, array $responses)
+ {
+ $responseSchema = $responses['200']['content']['application/json']['schema'] ??
+ $responses['201']['content']['application/json']['schema'] ??
+ $responses['202']['content']['application/json']['schema'] ??
+ $responses['203']['content']['application/json']['schema'] ??
+ $responses['204']['content']['application/json']['schema'] ?? null;
+
+ if (!$responseSchema) {
+ return null;
+ }
+ if ($responseSchema && isset($responseSchema['properties'])) {
+ $interfaceName = ucfirst($this->camelCase($operationId)) . "Response";
+ return $interfaceName;
+ } elseif ($responseSchema) {
+ return $this->getSchemaNameFromRef($responseSchema['$ref']);
+ }
+
+ throw new \Exception("Failed to find response schema for $operationId");
+ }
+
+ private function getResponseExample(string $operationId, array $responses)
+ {
+ $responseSchema = $responses['200']['content']['application/json']['schema'] ??
+ $responses['201']['content']['application/json']['schema'] ??
+ $responses['202']['content']['application/json']['schema'] ?? null;
+
+ if (empty($responseSchema)) {
+ return (object) [];
+ }
+
+ return $this->mockFromSchema($responseSchema);
+ }
+
+ private function mockFromSchema(array $responseSchema)
+ {
+ $response = [];
+ if (isset($responseSchema['properties'])) {
+ foreach ($responseSchema['properties'] as $key => $value) {
+ if (empty($value)) {
+ throw new Exception("Empty value for " . $key);
+ }
+ $response[$key] = $this->mockValue($value);
+ }
+ } elseif (isset($responseSchema['$ref'])) {
+ return $this->mockFromSchema($this->getSchemaByRef($responseSchema['$ref']));
+ }
+ return (object) $response;
+ }
+
+ private function mockValue(array $value)
+ {
+ if (!isset($value['type']) && isset($value['schema'])) {
+ $value = $value['schema'];
+ }
+ if (!isset($value['type']) && isset($value['allOf'])) {
+ return $this->mockValueFromObject($value);
+ }
+ if (!isset($value['type']) && isset($value['$ref'])) {
+ return $this->mockValueFromObject($value);
+ }
+ if (!isset($value['type'])) {
+ throw new \Exception("Failed to mock value for " . json_encode($value));
+ }
+ switch ($value['type']) {
+ case 'string':
+ switch ($value['format'] ?? null) {
+ case 'id':
+ return '1';
+ case 'date-time':
+ return '2025-04-23T00:00:00Z';
+ default:
+ return 'foo';
+ }
+ case 'integer':
+ case 'number':
+ return 1;
+ case 'boolean':
+ return true;
+ case 'array':
+ if (isset($value['items']['$ref'])) {
+ return [$this->mockValue($this->getSchemaByRef($value['items']['$ref']))];
+ $ref = explode('/', $value['items']['$ref']);
+ $ref = end($ref);
+ return [$this->mockValue($this->openapi['components']['schemas'][$ref])];
+ }
+ return [1, 2, 3];
+ case 'object':
+ return $this->mockValueFromObject($value);
+ default:
+ return $value;
+ }
+ }
+
+ private function mockValueFromObject(array $value)
+ {
+ $withProperties = $this->findItemWithKeyInArray($value['allOf'] ?? [], 'properties');
+ $withRef = $this->findItemWithKeyInArray($value['allOf'] ?? [], '$ref');
+ if (isset($value['allOf']) && $withProperties) {
+ return $this->mockFromSchema($withProperties);
+ } elseif (isset($value['allOf']) && $withRef) {
+ $ref = explode('/', $withRef['$ref']);
+ $ref = end($ref);
+ return $this->mockValue($this->openapi['components']['schemas'][$ref]);
+ } elseif (isset($value['properties'])) {
+ return $this->mockFromSchema($value);
+ }
+ return (object) ['foo' => $value];
+ }
+
+ private function findItemWithKeyInArray(array $array, string $key)
+ {
+ foreach ($array as $item) {
+ if (isset($item[$key])) {
+ return $item;
+ }
+ }
+ return null;
+ }
+
+ private function findResponseSchema(string $operationId, array $responseSchema, array $imports)
+ {
+ $responseProperties = $responseSchema['properties'] ?? null;
+ if ($responseProperties) {
+ $refs = $this->findRefs($responseProperties);
+ foreach ($refs as $ref) {
+ $imports[] = $this->getSchemaNameFromRef($ref);
+ }
+ } elseif (isset($responseSchema['$ref'])) {
+ $imports[] = $this->getSchemaNameFromRef($responseSchema['$ref']);
+ } else {
+ throw new \Exception("Failed to find response schema for $operationId");
+ }
+
+ return $imports;
+ }
+
+ private function findRefs(array $schema)
+ {
+ $refs = [];
+ foreach ($schema as $key => $value) {
+ if (isset($value['$ref'])) {
+ $refs[] = $value['$ref'];
+ }
+ if (is_array($value)) {
+ $refs = array_merge($refs, $this->findRefs($value));
+ }
+ }
+
+ return $refs;
+ }
+
+ /**
+ * Generate a TypeScript method for an API endpoint
+ */
+ protected function generateMethod($httpMethod, $path, $details, &$imports)
+ {
+ $operationId = $details['operationId'];
+ $methodName = $this->camelCase($operationId);
+ $summary = $details['summary'] ?? '';
+ $parameters = $details['parameters'] ?? [];
+ $requestBody = $details['requestBody'] ?? null;
+ $responses = $details['responses'] ?? [];
+
+ $parameters = $this->filterValidParameters($parameters);
+ // Determine method signature based on parameters and request body
+ $paramList = [];
+ $pathParams = [];
+ $queryParams = [];
+
+ // Process path parameters
+ foreach ($parameters as $param) {
+ if ($param['in'] === 'path') {
+ $pathParams[] = $param;
+ $paramType = $this->mapSwaggerTypeToTypescript($param['schema']['type'] ?? 'string');
+ $paramList[] = $this->camelCase($param['name']) . ": " . $paramType;
+ } elseif ($param['in'] === 'query') {
+ $queryParams[] = $param;
+ }
+ }
+
+ // Add request body parameter for POST/PUT methods
+ if (($httpMethod === 'post' || $httpMethod === 'put' || $httpMethod === 'patch')) {
+ if (isset($requestBody['content']['application/json']['schema']['$ref'])) {
+ $schemaRef = $requestBody['content']['application/json']['schema']['$ref'];
+ $schemaName = $this->getSchemaNameFromRef($schemaRef);
+ $imports[] = $schemaName;
+ $paramList[] = "data: " . $schemaName;
+ } else {
+ $paramList[] = "data: Record";
+ }
+ }
+
+ // Handle GET methods with query parameters
+ if (!empty($queryParams)) {
+ $queryParamTypeName = ucfirst($this->camelCase($operationId)) . "QueryParams";
+ $paramList[] = "params?: " . $queryParamTypeName;
+ }
+
+ // Determine return type
+ /*$returnType = 'void';
+ foreach ($responses as $code => $response) {
+ if ("$code"[0] === '2') { // 2xx response
+ if (isset($response['content']['application/json']['schema'])) {
+ $schema = $response['content']['application/json']['schema'];
+
+ if (isset($schema['$ref'])) {
+ $returnType = $this->getSchemaNameFromRef($schema['$ref']);
+ } elseif (isset($schema['type']) && $schema['type'] === 'object' && isset($schema['properties']['data']['type']) && $schema['properties']['data']['type'] === 'array') {
+ // Handle paginated response
+ if (isset($schema['properties']['data']['items']['$ref'])) {
+ $itemType = $this->getSchemaNameFromRef($schema['properties']['data']['items']['$ref']);
+ $returnType = "PaginatedResponse<" . $itemType . ">";
+ } else {
+ $returnType = "PaginatedResponse";
+ }
+ } else {
+ $returnType = "any";
+ }
+ }
+ break;
+ }
+ }*/
+
+ $returnType = $this->getResponseReference($operationId, $responses);
+ $responseExample = $this->getResponseExample($operationId, $responses);
+
+
+ // Build path with parameters
+ $apiPath = $path;
+ foreach ($pathParams as $param) {
+ $apiPath = str_replace('{' . $param['name'] . '}', '${' . $this->camelCase($param['name']) . '}', $apiPath);
+ }
+
+ return [
+ 'methodName' => $methodName,
+ 'summary' => $summary,
+ 'httpMethod' => $httpMethod,
+ 'paramList' => $paramList,
+ 'returnType' => $returnType,
+ 'responseExample' => $responseExample,
+ 'apiPath' => $apiPath,
+ 'queryParams' => $queryParams,
+ 'pathParams' => $pathParams,
+ 'requestBody' => $requestBody,
+ ];
+ }
+
+ private function filterValidParameters(array $parameters)
+ {
+ // add in=query to the parameters if it is not set
+ foreach ($parameters as $i => $param) {
+ if (isset($param['ref']) || isset($param['$ref'])) {
+ $ref = $param['ref'] ?? $param['$ref'];
+ $refParts = explode('/', $ref);
+ $refName = end($refParts);
+ $parameters[$i]['in'] = 'query';
+ $parameters[$i]['name'] = $refName;
+ } elseif (!isset($param['in'])) {
+ $parameters[$i]['in'] = 'query';
+ dd($parameters[$i]);
+ }
+ }
+ return $parameters;
+ return array_filter($parameters, function ($param) {
+ return isset($param['in']);
+ });
+ }
+
+ /**
+ * Generate a TypeScript composable for a tag
+ */
+ protected function generateComposableForTag($tag, $outputDir)
+ {
+ $tagLower = Str::camel($tag);
+ $className = "ProcessMaker" . ucfirst($tagLower) . "Api";
+ $hookName = "useProcessMaker" . ucfirst($tagLower);
+
+ $data = [
+ 'tagLower' => $tagLower,
+ 'className' => $className,
+ 'hookName' => $hookName
+ ];
+
+ $content = Blade::render($this->getStub('composable'), $data);
+ $this->files->put("$outputDir/" . $hookName . ".ts", $content);
+ }
+
+ /**
+ * Generate index files for the SDK
+ */
+ protected function generateIndexFiles($tags, $apiDir, $composablesDir, $typesDir, $outputDir)
+ {
+ // API index
+ $apiClasses = [];
+ foreach ($tags as $tag) {
+ $tagLower = Str::camel($tag);
+ $className = "ProcessMaker" . ucfirst($tagLower) . "Api";
+ $apiClasses[] = [
+ 'className' => $className,
+ 'tagLower' => $tagLower
+ ];
+ }
+ // sort apiClasses alphabetically ascending by className
+ usort($apiClasses, function($a, $b) {
+ return strcasecmp($a['className'], $b['className']);
+ });
+
+ $data = ['apiClasses' => $apiClasses];
+ $content = Blade::render($this->getStub('api-index'), $data);
+ $this->files->put("$apiDir/index.ts", $content);
+
+ // Composables index
+ $hooks = [];
+ foreach ($tags as $tag) {
+ $tagLower = Str::camel($tag);
+ $hookName = "useProcessMaker" . ucfirst($tagLower);
+ $hooks[] = $hookName;
+ }
+
+ $data = ['hooks' => $hooks];
+ $content = Blade::render($this->getStub('composables-index'), $data);
+ $this->files->put("$composablesDir/index.ts", $content);
+
+ // Main SDK index
+ $data = ['tags' => $tags];
+ $content = Blade::render($this->getStub('main-index'), $data);
+ $this->files->put("$outputDir/index.ts", $content);
+
+ // API Response type
+ $content = Blade::render($this->getStub('api-response'), []);
+ $this->files->put("$typesDir/api.ts", $content);
+
+ // README
+ $data = [
+ 'tags' => $tags,
+ 'firstTag' => !empty($tags) ? $tags[0] : null
+ ];
+ $content = Blade::render($this->getStub('readme'), $data);
+ $this->files->put("$outputDir/README.md", $content);
+ }
+
+ /**
+ * Generate interface from OpenAPI schema
+ */
+ protected function generateInterface($name, $schema)
+ {
+ $properties = $schema['properties'] ?? [];
+
+ $interfaceName = $this->formatInterfaceName($name);
+
+ if (empty($properties)) {
+ return "export interface $interfaceName {\n [key: string]: any;\n}";
+ }
+
+ $interface = "export interface $interfaceName {\n";
+
+ foreach ($properties as $propName => $propDetails) {
+ $interface .= " " . $propName;
+
+ // Check if property is required
+ $required = $schema['required'] ?? [];
+ if (!in_array($propName, $required)) {
+ $interface .= "?";
+ }
+
+ $interface .= ": " . $this->getTypescriptType($propDetails) . ";\n";
+ }
+
+ $interface .= "}";
+
+ return $interface;
+ }
+
+ /**
+ * Generate query param interface for GET endpoints
+ */
+ protected function generateQueryParamInterface($parameters, $tagLower, $operationId)
+ {
+ $parameters = $this->filterValidParameters($parameters);
+
+ $queryParams = array_filter($parameters, function ($param) {
+ return $param['in'] === 'query';
+ });
+
+ if (empty($queryParams)) {
+ return "";
+ }
+
+ $interfaceName = ucfirst($this->camelCase($operationId)) . "QueryParams";
+
+ $interface = "export interface " . $interfaceName . " {\n";
+
+ foreach ($queryParams as $param) {
+ $refType = $this->getTypeOf($param);
+ $interface .= " " . $this->camelCase($param['name']) . "?: " . $this->mapSwaggerTypeToTypescript($refType) . ";\n";
+ }
+
+ $interface .= "}";
+
+ return $interface;
+ }
+
+ private function getTypeOf(array $definition)
+ {
+ if (isset($definition['schema']['type'])) {
+ return $definition['schema']['type'];
+ }
+ if (isset($definition['$ref'])) {
+ return $this->getTypeOf($this->getSchemaByRef($definition['$ref']));
+ }
+
+ throw new Exception("Failed to get type of " . json_encode($definition));
+ }
+
+ private function generateResponseType($operationId, $responseSchema, $outputDir)
+ {
+ $interfaceName = ucfirst($this->camelCase($operationId)) . "Response";
+
+ $code = "export interface $interfaceName {\n";
+
+ foreach ($responseSchema['properties'] as $propName => $propDetails) {
+ $code .= " " . $propName . ": " . $this->getTypescriptType($propDetails) . ";\n";
+ }
+
+ $code .= "}";
+
+ return $code;
+ }
+
+ /**
+ * Format interface name to PascalCase
+ */
+ protected function formatInterfaceName($name)
+ {
+ $name = str_replace('#/components/schemas/', '', $name);
+
+ // Convert snake_case to PascalCase
+ return Str::studly($name);
+ }
+
+ /**
+ * Convert swagger type to TypeScript type
+ */
+ public function getTypescriptType($property)
+ {
+ if ($property === 'true' || $property === true) {
+ return 'any';
+ }
+ if (isset($property['$ref'])) {
+ $schema = $this->getSchemaByRef($property['$ref']);
+ if (isset($schema['schema'])) {
+ return $this->getTypescriptType($schema['schema']);
+ }
+ return $this->getSchemaNameFromRef($property['$ref']);
+ }
+ if (!isset($property['type']) && isset($property['schema']['type'])) {
+ return $this->getTypescriptType($property['schema']);
+ }
+ if (!isset($property['type'])) {
+ throw new Exception("Failed to get type of " . json_encode($property));
+ }
+ $type = $property['type'];
+
+ switch ($type) {
+ case 'integer':
+ return 'number';
+ case 'number':
+ return 'number';
+ case 'boolean':
+ return 'boolean';
+ case 'array':
+ if (isset($property['items']['$ref'])) {
+ $itemType = $this->getSchemaNameFromRef($property['items']['$ref']);
+ return $itemType . '[]';
+ } else {
+ $itemType = $this->getTypescriptType($property['items'] ?? ['type' => 'string']);
+ return $itemType . '[]';
+ }
+ case 'object':
+ if (isset($property['additionalProperties'])) {
+ $valueType = $this->getTypescriptType($property['additionalProperties']);
+ return "Record";
+ }
+ return 'Record';
+ default:
+ return 'string';
+ }
+ }
+
+ /**
+ * Get schema name from reference
+ */
+ protected function getSchemaNameFromRef($ref)
+ {
+ $parts = explode('/', $ref);
+ return $this->formatInterfaceName(end($parts));
+ }
+
+ /**
+ * Collect schema from reference for later processing
+ */
+ protected function collectSchemaFromRef($ref, &$schemas)
+ {
+ return;
+ // $schemaName = $this->getSchemaNameFromRef($ref);
+ // if ($schemaName !== 'UpdateUserGroups') {
+ // return;
+ // }
+ // dump($schemaName, $ref);
+ }
+
+ /**
+ * Get parameter value with appropriate conversion for TypeScript
+ */
+ protected function getParamValueConversion($paramName, $param)
+ {
+ $type = $param['schema']['type'] ?? 'string';
+
+ if ($type === 'integer' || $type === 'number') {
+ return "params.$paramName.toString()";
+ }
+
+ return "params.$paramName";
+ }
+
+ /**
+ * Convert string to camelCase
+ */
+ protected function camelCase($str)
+ {
+ return Str::camel($str);
+ }
+
+ /**
+ * Get stub template content
+ */
+ protected function getStub($type)
+ {
+ return $this->files->get(resource_path("stubs/api2typescript/{$type}.blade.php"));
+ }
+}
diff --git a/ProcessMaker/Events/BaseEmailEvent.php b/ProcessMaker/Events/BaseEmailEvent.php
new file mode 100644
index 0000000000..d70747ed32
--- /dev/null
+++ b/ProcessMaker/Events/BaseEmailEvent.php
@@ -0,0 +1,86 @@
+sent_email;
+ $emailIdentifier = $tracker->getHeader('X-ProcessMaker-Email-ID');
+ $messageEventId = $tracker->getHeader($this->getMessageEventIdHeader());
+ $requestIdentifier = $tracker->getHeader('X-ProcessMaker-Request-ID');
+
+ // Log the email event for debugging
+ Log::debug($this->getEventType() . ' email event', [
+ 'email_id' => $emailIdentifier,
+ 'message_event_id' => $messageEventId,
+ 'request_id' => $requestIdentifier,
+ ]);
+
+ if ($requestIdentifier && $messageEventId) {
+ $request = ProcessRequest::where('id', $requestIdentifier)->first();
+ if ($request) {
+ $data = [
+ 'email_id' => $emailIdentifier,
+ ];
+ WorkflowManager::triggerMessageEvent($request, $messageEventId, $data);
+ } else {
+ Log::warning($this->getEventType() . ' but process request not found', [
+ 'request_id' => $requestIdentifier,
+ ]);
+ }
+ } else {
+ // Only log a warning if email tracking was explicitly enabled for this email
+ if ($emailIdentifier) {
+ Log::warning($this->getEventType() . ' but missing required headers', [
+ 'email_id' => $emailIdentifier,
+ 'message_event_id' => $messageEventId,
+ 'request_id' => $requestIdentifier,
+ ]);
+ }
+ }
+ } catch (\Exception $e) {
+ Log::error('Error handling ' . $this->getEventType() . ' event', [
+ 'error' => $e->getMessage(),
+ 'trace' => $e->getTraceAsString(),
+ ]);
+ }
+ }
+}
diff --git a/ProcessMaker/Events/BouncedEmail.php b/ProcessMaker/Events/BouncedEmail.php
new file mode 100644
index 0000000000..55b3266e7a
--- /dev/null
+++ b/ProcessMaker/Events/BouncedEmail.php
@@ -0,0 +1,38 @@
+sent_email;
+ $emailIdentifier = $tracker->getHeader('X-ProcessMaker-Email-ID');
+ $messageEventId = $tracker->getHeader('X-ProcessMaker-Sent-Message-Event-ID');
+ $requestIdentifier = $tracker->getHeader('X-ProcessMaker-Request-ID');
+
+ if ($requestIdentifier && $messageEventId) {
+ $request = ProcessRequest::where('id', $requestIdentifier)->first();
+ if ($request) {
+ $data = [
+ 'email_id' => $emailIdentifier,
+ ];
+ WorkflowManager::triggerMessageEvent($request, $messageEventId, $data);
+ }
+ }
+ }
+}
diff --git a/ProcessMaker/Events/EmailComplaint.php b/ProcessMaker/Events/EmailComplaint.php
new file mode 100644
index 0000000000..9ae74f0a79
--- /dev/null
+++ b/ProcessMaker/Events/EmailComplaint.php
@@ -0,0 +1,41 @@
+processEmailEvent($event);
+ }
+
+ /**
+ * @inheritdoc
+ */
+ protected function getEventType(): string
+ {
+ return 'Complaint';
+ }
+
+ /**
+ * @inheritdoc
+ */
+ protected function getMessageEventIdHeader(): string
+ {
+ return 'X-ProcessMaker-Complaint-Message-Event-ID';
+ }
+}
diff --git a/ProcessMaker/Events/EmailDelivered.php b/ProcessMaker/Events/EmailDelivered.php
new file mode 100644
index 0000000000..8ea95fde4d
--- /dev/null
+++ b/ProcessMaker/Events/EmailDelivered.php
@@ -0,0 +1,41 @@
+processEmailEvent($event);
+ }
+
+ /**
+ * @inheritdoc
+ */
+ protected function getEventType(): string
+ {
+ return 'Delivered';
+ }
+
+ /**
+ * @inheritdoc
+ */
+ protected function getMessageEventIdHeader(): string
+ {
+ return 'X-ProcessMaker-Delivered-Message-Event-ID';
+ }
+}
diff --git a/ProcessMaker/Events/EmailLinkClicked.php b/ProcessMaker/Events/EmailLinkClicked.php
new file mode 100644
index 0000000000..640ce2568e
--- /dev/null
+++ b/ProcessMaker/Events/EmailLinkClicked.php
@@ -0,0 +1,41 @@
+processEmailEvent($event);
+ }
+
+ /**
+ * @inheritdoc
+ */
+ protected function getEventType(): string
+ {
+ return 'Link clicked';
+ }
+
+ /**
+ * @inheritdoc
+ */
+ protected function getMessageEventIdHeader(): string
+ {
+ return 'X-ProcessMaker-Link-Clicked-Message-Event-ID';
+ }
+}
diff --git a/ProcessMaker/Events/EmailSent.php b/ProcessMaker/Events/EmailSent.php
new file mode 100644
index 0000000000..a993329962
--- /dev/null
+++ b/ProcessMaker/Events/EmailSent.php
@@ -0,0 +1,41 @@
+processEmailEvent($event);
+ }
+
+ /**
+ * @inheritdoc
+ */
+ protected function getEventType(): string
+ {
+ return 'Sent';
+ }
+
+ /**
+ * @inheritdoc
+ */
+ protected function getMessageEventIdHeader(): string
+ {
+ return 'X-ProcessMaker-Sent-Message-Event-ID';
+ }
+}
diff --git a/ProcessMaker/Events/EmailViewed.php b/ProcessMaker/Events/EmailViewed.php
new file mode 100644
index 0000000000..6e258facea
--- /dev/null
+++ b/ProcessMaker/Events/EmailViewed.php
@@ -0,0 +1,41 @@
+processEmailEvent($event);
+ }
+
+ /**
+ * @inheritdoc
+ */
+ protected function getEventType(): string
+ {
+ return 'Viewed';
+ }
+
+ /**
+ * @inheritdoc
+ */
+ protected function getMessageEventIdHeader(): string
+ {
+ return 'X-ProcessMaker-Viewed-Message-Event-ID';
+ }
+}
diff --git a/ProcessMaker/Events/MessageEventCaught.php b/ProcessMaker/Events/MessageEventCaught.php
new file mode 100644
index 0000000000..1eb2ae3bac
--- /dev/null
+++ b/ProcessMaker/Events/MessageEventCaught.php
@@ -0,0 +1,73 @@
+
+ */
+ public function broadcastOn(): array
+ {
+ $channels = [
+ new PrivateChannel('ProcessMaker.Models.ProcessRequest.' . $this->processRequest->getKey()),
+ ];
+ $hasParent = $this->processRequest->parent_request_id;
+ if ($hasParent) {
+ $channels[] = new PrivateChannel('ProcessMaker.Models.ProcessRequest.' . $this->processRequest->parent_request_id . '.SubProcesses');
+ }
+ return $channels;
+ }
+
+ /**
+ * Set the event name
+ *
+ * @return string
+ */
+ public function broadcastAs()
+ {
+ return 'MessageEventCaught';
+ }
+
+ /**
+ * Get the data to broadcast.
+ *
+ * @return array
+ */
+ public function broadcastWith(): array
+ {
+ return [
+ 'event' => [
+ 'id' => $this->message->getId(),
+ 'name' => $this->message->getName(),
+ ],
+ 'element' => [
+ 'id' => $this->node->getId(),
+ 'name' => $this->node->getName(),
+ ],
+ 'data' => (object) $this->message->getData($this->processRequest),
+ ];
+ }
+}
diff --git a/ProcessMaker/Events/MessageEventThrown.php b/ProcessMaker/Events/MessageEventThrown.php
new file mode 100644
index 0000000000..7416deb04a
--- /dev/null
+++ b/ProcessMaker/Events/MessageEventThrown.php
@@ -0,0 +1,73 @@
+
+ */
+ public function broadcastOn(): array
+ {
+ $channels = [
+ new PrivateChannel('ProcessMaker.Models.ProcessRequest.' . $this->processRequest->getKey()),
+ ];
+ $hasParent = $this->processRequest->parent_request_id;
+ if ($hasParent) {
+ $channels[] = new PrivateChannel('ProcessMaker.Models.ProcessRequest.' . $this->processRequest->parent_request_id . '.SubProcesses');
+ }
+ return $channels;
+ }
+
+ /**
+ * Set the event name
+ *
+ * @return string
+ */
+ public function broadcastAs()
+ {
+ return 'MessageEventThrown';
+ }
+
+ /**
+ * Get the data to broadcast.
+ *
+ * @return array
+ */
+ public function broadcastWith(): array
+ {
+ return [
+ 'event' => [
+ 'id' => $this->message->getId(),
+ 'name' => $this->message->getName(),
+ ],
+ 'element' => [
+ 'id' => $this->node->getId(),
+ 'name' => $this->node->getName(),
+ ],
+ 'data' => (object) $this->message->getData($this->processRequest),
+ ];
+ }
+}
diff --git a/ProcessMaker/Facades/WorkflowManager.php b/ProcessMaker/Facades/WorkflowManager.php
index 8ae67c78d0..a26df908f6 100644
--- a/ProcessMaker/Facades/WorkflowManager.php
+++ b/ProcessMaker/Facades/WorkflowManager.php
@@ -25,6 +25,8 @@
* @method static bool registerServiceImplementation($implementation, $class)
* @method static bool existsServiceImplementation($implementation)
* @method static bool runServiceImplementation($implementation, array $data, array $config, $tokenId = '')
+ * @method static void triggerBoundaryEvent(\ProcessMaker\Models\Process $process, \ProcessMaker\Models\ProcessRequest $request, \ProcessMaker\Nayra\Contracts\Bpmn\TokenInterface $token, \ProcessMaker\Nayra\Contracts\Bpmn\BoundaryEventInterface $boundaryEvent)
+ * @method static void triggerMessageEvent(\ProcessMaker\Models\ProcessRequest $request, string $messageEventId, array $data)
*/
class WorkflowManager extends Facade
{
diff --git a/ProcessMaker/Http/Controllers/Api/NotificationController.php b/ProcessMaker/Http/Controllers/Api/NotificationController.php
index c94d72c1e3..16374aedb9 100644
--- a/ProcessMaker/Http/Controllers/Api/NotificationController.php
+++ b/ProcessMaker/Http/Controllers/Api/NotificationController.php
@@ -64,6 +64,7 @@ class NotificationController extends Controller
* ),
* @OA\Property(
* property="meta",
+ * type="object",
* @OA\Schema(ref="#/components/schemas/metadata"),
* ),
* ),
diff --git a/ProcessMaker/Http/Controllers/Api/OpenApiSpec.php b/ProcessMaker/Http/Controllers/Api/OpenApiSpec.php
index f99e69b916..17b48e71b1 100644
--- a/ProcessMaker/Http/Controllers/Api/OpenApiSpec.php
+++ b/ProcessMaker/Http/Controllers/Api/OpenApiSpec.php
@@ -44,6 +44,12 @@
* @OA\Schema(type="string", enum={"asc", "desc"}, default="asc"),
* ),
* @OA\Parameter(
+ * parameter="page",
+ * name="page",
+ * in="query",
+ * @OA\Schema(type="integer", default="1"),
+ * ),
+ * @OA\Parameter(
* parameter="per_page",
* name="per_page",
* in="query",
@@ -57,6 +63,13 @@
* @OA\Schema(type="string", default=""),
* ),
* @OA\Parameter(
+ * parameter="fields",
+ * name="fields",
+ * in="query",
+ * description="Fields to map the response object.",
+ * @OA\Schema(type="object"),
+ * ),
+ * @OA\Parameter(
* parameter="member_id",
* name="member_id",
* in="query",
@@ -74,6 +87,13 @@
* in="query",
* @OA\Schema(type="string", default=""),
* ),
+ * @OA\Parameter(
+ * parameter="pmql",
+ * name="pmql",
+ * in="query",
+ * description="PMQL query to filter results",
+ * @OA\Schema(type="string"),
+ * ),
* @OA\Schema(
* schema="DateTime",
* @OA\Property(property="date", type="string"),
diff --git a/ProcessMaker/Http/Controllers/Api/PermissionController.php b/ProcessMaker/Http/Controllers/Api/PermissionController.php
index 03b468fa22..f5636d846d 100644
--- a/ProcessMaker/Http/Controllers/Api/PermissionController.php
+++ b/ProcessMaker/Http/Controllers/Api/PermissionController.php
@@ -48,6 +48,7 @@ public function index(Request $request)
* @OA\Put(
* path="/permissions",
* summary="Update the permissions of a user",
+ * operationId="updatePermissions",
* tags={"Permissions"},
*
* @OA\RequestBody(
diff --git a/ProcessMaker/Http/Controllers/Api/ProcessController.php b/ProcessMaker/Http/Controllers/Api/ProcessController.php
index b782c2cf0b..1b9e6dc39c 100644
--- a/ProcessMaker/Http/Controllers/Api/ProcessController.php
+++ b/ProcessMaker/Http/Controllers/Api/ProcessController.php
@@ -87,6 +87,7 @@ class ProcessController extends Controller
* @OA\Parameter(ref="#/components/parameters/per_page"),
* @OA\Parameter(ref="#/components/parameters/status"),
* @OA\Parameter(ref="#/components/parameters/include"),
+ * @OA\Parameter(ref="#/components/parameters/pmql"),
* @OA\Parameter(
* name="simplified_data_for_selector",
* in="query",
@@ -1310,6 +1311,7 @@ public function downloadBpmn(Request $request, Process $process)
* @OA\Head(
* path="/processes/import/{code}/is_ready",
* summary="Check if the import is ready",
+ * operationId="importReady",
* tags={"Processes"},
*
* @OA\Parameter(
diff --git a/ProcessMaker/Http/Controllers/Api/ProcessRequestController.php b/ProcessMaker/Http/Controllers/Api/ProcessRequestController.php
index a183a22f9e..cc59e829fe 100644
--- a/ProcessMaker/Http/Controllers/Api/ProcessRequestController.php
+++ b/ProcessMaker/Http/Controllers/Api/ProcessRequestController.php
@@ -547,6 +547,65 @@ public function activateIntermediateEvent(ProcessRequest $request, $event)
return response([]);
}
+ /**
+ * Trigger a boundary event
+ *
+ * @param ProcessRequest $request
+ * @param string $event
+ * @return void
+ *
+ * @OA\Post(
+ * path="/requests/{process_request_id}/boundary/{boundary_event_id}",
+ * summary="Trigger a boundary event",
+ * operationId="triggerBoundaryEvent",
+ * tags={"Process Requests"},
+ * @OA\Parameter(
+ * description="ID of process request",
+ * in="path",
+ * name="process_request_id",
+ * required=true,
+ * @OA\Schema(
+ * type="integer",
+ * )
+ * ),
+ * @OA\Parameter(
+ * description="ID of boundary event",
+ * in="path",
+ * name="boundary_event_id",
+ * required=true,
+ * @OA\Schema(
+ * type="string",
+ * )
+ * ),
+ * @OA\RequestBody(
+ * @OA\JsonContent(
+ * required={"data"},
+ * @OA\Property(property="data", type="object"),
+ * )
+ * ),
+ * @OA\Response(
+ * response=204,
+ * description="success",
+ * ),
+ * )
+ */
+ public function triggerBoundaryEvent(ProcessRequest $request, $boundaryEventId)
+ {
+ $data = (array) request()->json()->all();
+ // Get the process definition
+ $definitions = $request->getVersionDefinitions();
+ $boundaryEvent = $definitions->getBoundaryEvent($boundaryEventId);
+ $activity = $boundaryEvent->getAttachedTo();
+ $tokens = $request->tokens()
+ ->where('element_id', $activity->getId())
+ ->where('status', 'ACTIVE')->get();
+ foreach ($tokens as $token) {
+ WorkflowManager::triggerBoundaryEvent($request->process, $request, $token, $boundaryEvent, $data);
+ }
+
+ return response([], 204);
+ }
+
/**
* Parse the whitelist parameter
*
diff --git a/ProcessMaker/Http/Controllers/Api/TaskAssignmentController.php b/ProcessMaker/Http/Controllers/Api/TaskAssignmentController.php
index 05568ee8c5..7d35cf5c5e 100644
--- a/ProcessMaker/Http/Controllers/Api/TaskAssignmentController.php
+++ b/ProcessMaker/Http/Controllers/Api/TaskAssignmentController.php
@@ -176,10 +176,6 @@ public function update(ProcessTaskAssignment $task_assignment, Request $request)
* type="integer",
* )
* ),
- * @OA\RequestBody(
- * required=true,
- * @OA\JsonContent(ref="#/components/schemas/taskAssignmentsEditable")
- * ),
* @OA\Response(
* response=200,
* description="success",
diff --git a/ProcessMaker/Http/Controllers/Api/TaskController.php b/ProcessMaker/Http/Controllers/Api/TaskController.php
index 2d691af0ee..789c16b30f 100644
--- a/ProcessMaker/Http/Controllers/Api/TaskController.php
+++ b/ProcessMaker/Http/Controllers/Api/TaskController.php
@@ -101,9 +101,12 @@ class TaskController extends Controller
* )
* ),
* @OA\Parameter(ref="#/components/parameters/filter"),
+ * @OA\Parameter(ref="#/components/parameters/pmql"),
* @OA\Parameter(ref="#/components/parameters/order_by"),
* @OA\Parameter(ref="#/components/parameters/order_direction"),
* @OA\Parameter(ref="#/components/parameters/include"),
+ * @OA\Parameter(ref="#/components/parameters/page"),
+ * @OA\Parameter(ref="#/components/parameters/per_page"),
*
* @OA\Response(
* response=200,
diff --git a/ProcessMaker/Http/Controllers/Api/UserController.php b/ProcessMaker/Http/Controllers/Api/UserController.php
index 0ecbf49fe0..b26e26b2a1 100644
--- a/ProcessMaker/Http/Controllers/Api/UserController.php
+++ b/ProcessMaker/Http/Controllers/Api/UserController.php
@@ -946,4 +946,18 @@ public function updateLanguage(Request $request)
return response([], 204);
}
+
+ public function current()
+ {
+ return response([
+ 'data' => Auth::user(),
+ ], 200);
+ }
+
+ public function logout(Request $request)
+ {
+ $request->user()->token()->revoke();
+
+ return response()->json(['message' => 'OK']);
+ }
}
diff --git a/ProcessMaker/Http/Controllers/Api/V1_1/ProcessVariableController.php b/ProcessMaker/Http/Controllers/Api/V1_1/ProcessVariableController.php
index d57af422fb..ec45f6fb7d 100644
--- a/ProcessMaker/Http/Controllers/Api/V1_1/ProcessVariableController.php
+++ b/ProcessMaker/Http/Controllers/Api/V1_1/ProcessVariableController.php
@@ -66,6 +66,7 @@ class ProcessVariableController extends Controller
* )
* @OA\Get(
* path="/processes/variables",
+ * operationId="getProcessesVariables",
* summary="Get variables for multiple processes with pagination",
* servers={
* @OA\Server(url=L5_SWAGGER_API_V1_1, description="API v1.1 Server")
diff --git a/ProcessMaker/Http/Controllers/Auth/LoginController.php b/ProcessMaker/Http/Controllers/Auth/LoginController.php
index 190475ec1b..a223b6853b 100644
--- a/ProcessMaker/Http/Controllers/Auth/LoginController.php
+++ b/ProcessMaker/Http/Controllers/Auth/LoginController.php
@@ -288,6 +288,10 @@ private function forgetUserSession()
public function loggedOut(Request $request)
{
+ if ($request->has('redirectTo')) {
+ return redirect($request->get('redirectTo'));
+ }
+
$response = redirect(route('login'));
if ($request->has('timeout')) {
$response->with('timeout', true);
diff --git a/ProcessMaker/Http/Controllers/Process/ScreenBuilderController.php b/ProcessMaker/Http/Controllers/Process/ScreenBuilderController.php
index c356f4c27b..d5bc676b4d 100644
--- a/ProcessMaker/Http/Controllers/Process/ScreenBuilderController.php
+++ b/ProcessMaker/Http/Controllers/Process/ScreenBuilderController.php
@@ -22,6 +22,11 @@ class ScreenBuilderController extends Controller
*/
public function edit(ScreenBuilderManager $manager, Screen $screen, $processId = null)
{
+ // Check if the screen is external url
+ if ($screen->config[0]['url'] ?? null) {
+ return redirect($screen->config[0]['url']);
+ }
+
/**
* Emit the ModelerStarting event, passing in our ModelerManager instance. This will
* allow packages to add additional javascript for modeler initialization which
diff --git a/ProcessMaker/Http/Kernel.php b/ProcessMaker/Http/Kernel.php
index 97ffae0d6c..c083dbee34 100644
--- a/ProcessMaker/Http/Kernel.php
+++ b/ProcessMaker/Http/Kernel.php
@@ -24,6 +24,7 @@ class Kernel extends HttpKernel
Middleware\BrowserCache::class,
ServerTimingMiddleware::class,
Middleware\FileSizeCheck::class,
+ \Illuminate\Http\Middleware\HandleCors::class,
];
/**
@@ -89,7 +90,7 @@ class Kernel extends HttpKernel
'no-cache' => Middleware\NoCache::class,
'admin' => Middleware\IsAdmin::class,
'etag' => Middleware\Etag\HandleEtag::class,
- 'file_size_check' => Middleware\FileSizeCheck::class
+ 'file_size_check' => Middleware\FileSizeCheck::class,
];
/**
diff --git a/ProcessMaker/Listeners/BpmnSubscriber.php b/ProcessMaker/Listeners/BpmnSubscriber.php
index c7f0f7f810..0a862a0bca 100644
--- a/ProcessMaker/Listeners/BpmnSubscriber.php
+++ b/ProcessMaker/Listeners/BpmnSubscriber.php
@@ -3,16 +3,21 @@
namespace ProcessMaker\Listeners;
use Exception;
+use Illuminate\Support\Facades\App;
use Illuminate\Support\Facades\Log;
use Illuminate\Support\Facades\Notification;
use ProcessMaker\Events\ActivityAssigned;
use ProcessMaker\Events\ActivityCompleted;
+use ProcessMaker\Events\MessageEventCaught;
+use ProcessMaker\Events\MessageEventThrown;
use ProcessMaker\Events\ProcessCompleted;
use ProcessMaker\Facades\Metrics;
use ProcessMaker\Facades\WorkflowManager;
use ProcessMaker\Jobs\TerminateRequestEndEvent;
+use ProcessMaker\Managers\DataManager;
use ProcessMaker\Models\Comment;
use ProcessMaker\Models\FormalExpression;
+use ProcessMaker\Models\Message;
use ProcessMaker\Models\ProcessRequest;
use ProcessMaker\Models\ProcessRequestToken;
use ProcessMaker\Nayra\Bpmn\Events\ActivityActivatedEvent;
@@ -21,7 +26,9 @@
use ProcessMaker\Nayra\Bpmn\Events\ProcessInstanceCompletedEvent;
use ProcessMaker\Nayra\Bpmn\Events\ProcessInstanceCreatedEvent;
use ProcessMaker\Nayra\Contracts\Bpmn\ActivityInterface;
+use ProcessMaker\Nayra\Contracts\Bpmn\CatchEventInterface;
use ProcessMaker\Nayra\Contracts\Bpmn\ConditionalEventDefinitionInterface;
+use ProcessMaker\Nayra\Contracts\Bpmn\EntityInterface;
use ProcessMaker\Nayra\Contracts\Bpmn\ErrorInterface;
use ProcessMaker\Nayra\Contracts\Bpmn\IntermediateCatchEventInterface;
use ProcessMaker\Nayra\Contracts\Bpmn\MessageEventDefinitionInterface;
@@ -29,6 +36,7 @@
use ProcessMaker\Nayra\Contracts\Bpmn\ScriptTaskInterface;
use ProcessMaker\Nayra\Contracts\Bpmn\ServiceTaskInterface;
use ProcessMaker\Nayra\Contracts\Bpmn\TerminateEventDefinitionInterface;
+use ProcessMaker\Nayra\Contracts\Bpmn\ThrowEventInterface;
use ProcessMaker\Nayra\Contracts\Bpmn\TimerEventDefinitionInterface;
use ProcessMaker\Nayra\Contracts\Bpmn\TokenInterface;
use ProcessMaker\Nayra\Contracts\Bpmn\TransitionInterface;
@@ -247,6 +255,21 @@ public function onIntermediateCatchEventActivated(IntermediateCatchEventInterfac
foreach ($event->getEventDefinitions() as $eventDefinition) {
foreach ($messages as $interface => $message) {
if (is_subclass_of($eventDefinition, $interface)) {
+ $bpmnMessage = $eventDefinition->getPayload();
+ if ($bpmnMessage) {
+ event(new MessageEventCaught($token->getInstance(), $token->getOwnerElement(), $bpmnMessage));
+ devtools(
+ '▶︎ MessageEventCaught',
+ $bpmnMessage->getName() ?? '(null)',
+ $bpmnMessage->getId() ?? '(null)',
+ [
+ 'Payload' => json_encode(
+ (object) $bpmnMessage->getData($token->getInstance()),
+ JSON_PRETTY_PRINT
+ )
+ ]
+ );
+ }
$comment = new Comment([
'user_id' => null,
'commentable_type' => ProcessRequest::class,
@@ -279,7 +302,8 @@ public function updateDataWithFlowTransition($transition, $flow, $instance)
// Exit if no variable or expression is set
$config = json_decode($flow->getProperties()['config'], true);
- if (empty($config['update_data'])
+ if (
+ empty($config['update_data'])
|| empty($config['update_data']['variable'])
|| empty($config['update_data']['expression'])
) {
@@ -316,6 +340,45 @@ public function onTerminateEndEvent($event)
});
}
+ public function onMessageEventDefinition(ThrowEventInterface $node, TokenInterface $token, Message $message)
+ {
+ event(new MessageEventThrown($token->getInstance(), $node, $message));
+ devtools(
+ '▶︎ MessageEventThrown',
+ $message->getName() ?? '(null)',
+ $message->getId() ?? '(null)',
+ [
+ 'Payload' => json_encode(
+ (object) $message->getData($token->getInstance()),
+ JSON_PRETTY_PRINT
+ )
+ ]
+ );
+ }
+
+ public function onMessageEventCaught(CatchEventInterface $node, TokenInterface $token)
+ {
+ foreach ($node->getEventDefinitions() as $eventDefinition) {
+ if ($eventDefinition instanceof MessageEventDefinitionInterface) {
+ $bpmnMessage = $eventDefinition->getPayload();
+ if ($bpmnMessage) {
+ event(new MessageEventCaught($token->getInstance(), $token->getOwnerElement(), $bpmnMessage));
+ devtools(
+ '▶︎ MessageEventCaught',
+ $bpmnMessage->getName() ?? '(null)',
+ $bpmnMessage->getId() ?? '(null)',
+ [
+ 'Payload' => json_encode(
+ (object) $bpmnMessage->getData($token->getInstance()),
+ JSON_PRETTY_PRINT
+ )
+ ]
+ );
+ }
+ }
+ }
+ }
+
/**
* Subscription.
*
@@ -340,5 +403,45 @@ public function subscribe($events)
$events->listen(IntermediateCatchEventInterface::EVENT_CATCH_TOKEN_ARRIVES, static::class . '@onIntermediateCatchEventActivated');
$events->listen(TerminateEventDefinitionInterface::EVENT_THROW_EVENT_DEFINITION, static::class . '@onTerminateEndEvent');
+ $events->listen(MessageEventDefinitionInterface::EVENT_THROW_EVENT_DEFINITION, static::class . '@onMessageEventDefinition');
+ $events->listen(IntermediateCatchEventInterface::EVENT_CATCH_MESSAGE_CATCH, static::class . '@onMessageEventCaught');
+
+ // Log devtools events for local and testing environments
+ if (App::environment('local') || App::environment('testing')) {
+ $events->listen('*', function ($event, $args) {
+ $hasBackslash = strpos($event, '\\') !== false;
+ if (!$hasBackslash && count($args) > 0) {
+ $token = isset($args[1]) && ($args[1] instanceof ProcessRequestToken) ? $args[1] : null;
+ $payload = $args[0];
+ if (
+ $payload instanceof ActivityCompletedEvent
+ || $payload instanceof ActivityActivatedEvent
+ || $payload instanceof ActivityClosedEvent
+ ) {
+ $token = $payload->token;
+ $payload = $payload->activity;
+ }
+
+ if ($payload instanceof EntityInterface) {
+ $element = $payload->getBpmnElement();
+ $document = $payload->getOwnerDocument();
+ $xml = $element ? $document->saveXML($element) : '';
+ $details = [
+ 'Node' => $xml
+ ];
+ if ($token) {
+ $dm = new DataManager();
+ $details['Data'] = json_encode((object) $dm->getData($token), JSON_PRETTY_PRINT);
+ }
+ devtools(
+ $event,
+ $payload->getName() ?? '(null)',
+ $payload->getId() ?? '(null)',
+ $details
+ );
+ }
+ }
+ });
+ }
}
}
diff --git a/ProcessMaker/Managers/DataManager.php b/ProcessMaker/Managers/DataManager.php
index b3566d7509..167584603e 100644
--- a/ProcessMaker/Managers/DataManager.php
+++ b/ProcessMaker/Managers/DataManager.php
@@ -127,7 +127,7 @@ private function loadTokenData(array $data = [], ProcessRequestToken $token = nu
}
// Magic Variable: _user
- $data = $this->loadUserData($data, $token);
+ $data = $this->loadUserData($data ?? [], $token);
// Magic Variable: _request
$request = $token->getInstance() ?: $token->processRequest;
diff --git a/ProcessMaker/Models/ProcessRequest.php b/ProcessMaker/Models/ProcessRequest.php
index aee92ce58b..ad10c5e0a2 100644
--- a/ProcessMaker/Models/ProcessRequest.php
+++ b/ProcessMaker/Models/ProcessRequest.php
@@ -88,7 +88,7 @@
* @OA\Property(property="process_category_id", type="string", format="id"),
* @OA\Property(property="created_at", type="string", format="date-time"),
* @OA\Property(property="updated_at", type="string", format="date-time"),
- * @OA\Property(property="user", @OA\Schema(ref="#/components/schemas/users")),
+ * @OA\Property(property="user", type="object", @OA\Schema(ref="#/components/schemas/users")),
* @OA\Property(property="participants", type="array", @OA\Items(ref="#/components/schemas/users")),
* )
* },
diff --git a/ProcessMaker/Models/TimerExpression.php b/ProcessMaker/Models/TimerExpression.php
index af70744e23..069fed3bd6 100644
--- a/ProcessMaker/Models/TimerExpression.php
+++ b/ProcessMaker/Models/TimerExpression.php
@@ -87,7 +87,13 @@ public function getLanguage()
public function __invoke($data)
{
$expression = $this->getProperty(FormalExpressionInterface::BPMN_PROPERTY_BODY);
- $expression = $this->mustacheTimerExpression($expression, $data);
+ $isFeel = str_contains($this->getProperty('type'), 'tFormalExpression');
+ if ($isFeel) {
+ $feel = new FeelExpressionEvaluator();
+ $expression = $feel->render($expression, $data);
+ } else {
+ $expression = $this->mustacheTimerExpression($expression, $data);
+ }
return $this->getDateExpression($expression)
?: $this->getCycleExpression($expression)
diff --git a/ProcessMaker/Nayra/Managers/WorkflowManagerDefault.php b/ProcessMaker/Nayra/Managers/WorkflowManagerDefault.php
index 0f757aa7e2..f1f9772215 100644
--- a/ProcessMaker/Nayra/Managers/WorkflowManagerDefault.php
+++ b/ProcessMaker/Nayra/Managers/WorkflowManagerDefault.php
@@ -18,13 +18,17 @@
use ProcessMaker\Jobs\StartEvent;
use ProcessMaker\Jobs\ThrowMessageEvent;
use ProcessMaker\Jobs\ThrowSignalEvent;
+use ProcessMaker\Managers\DataManager;
use ProcessMaker\Models\FormalExpression;
use ProcessMaker\Models\Process as Definitions;
use ProcessMaker\Models\ProcessRequest;
use ProcessMaker\Models\ProcessRequestToken as Token;
+use ProcessMaker\Nayra\Contracts\Bpmn\ActivityInterface;
use ProcessMaker\Nayra\Contracts\Bpmn\BoundaryEventInterface;
use ProcessMaker\Nayra\Contracts\Bpmn\EntityInterface;
use ProcessMaker\Nayra\Contracts\Bpmn\EventDefinitionInterface;
+use ProcessMaker\Nayra\Contracts\Bpmn\IntermediateCatchEventInterface;
+use ProcessMaker\Nayra\Contracts\Bpmn\MessageEventDefinitionInterface;
use ProcessMaker\Nayra\Contracts\Bpmn\ProcessInterface;
use ProcessMaker\Nayra\Contracts\Bpmn\ScriptTaskInterface;
use ProcessMaker\Nayra\Contracts\Bpmn\ServiceTaskInterface;
@@ -137,6 +141,42 @@ public function triggerBoundaryEvent(
BoundaryEvent::dispatchSync($definitions, $instance, $token, $boundaryEvent, $data);
}
+ /**
+ * Trigger a message event
+ *
+ * @param ProcessRequest $request
+ * @param string $messageEventId
+ * @param array $data
+ */
+ public function triggerMessageEvent(ProcessRequest $request, string $messageEventId, array $data)
+ {
+ // find active tokens that are waiting for this message event
+ $tokens = $request->tokens()->where('status', ActivityInterface::TOKEN_STATE_ACTIVE)->get();
+ foreach ($tokens as $token) {
+ $element = $token->getDefinition(true);
+ $isIntermediateCatchEvent = $element instanceof IntermediateCatchEventInterface;
+ $isTask = $element instanceof ActivityInterface;
+ if ($isIntermediateCatchEvent) {
+ foreach ($element->getEventDefinitions() as $eventDefinition) {
+ if ($eventDefinition instanceof MessageEventDefinitionInterface && $eventDefinition->getPayload()->getId() === $messageEventId) {
+ CatchEvent::dispatchSync($request->process, $request, $token, $data);
+ }
+ }
+ } elseif ($isTask) {
+ $hasBoundaryEvent = $element->getBoundaryEvents()->count() > 0;
+ if ($hasBoundaryEvent) {
+ foreach ($element->getBoundaryEvents() as $boundaryEvent) {
+ foreach ($boundaryEvent->getEventDefinitions() as $eventDefinition) {
+ if ($eventDefinition instanceof MessageEventDefinitionInterface && $eventDefinition->getPayload()?->getId() === $messageEventId) {
+ BoundaryEvent::dispatchSync($request->process, $request, $token, $boundaryEvent, $data);
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+
/**
* Trigger an start event and return the instance.
*
diff --git a/ProcessMaker/Providers/BroadcastServiceProvider.php b/ProcessMaker/Providers/BroadcastServiceProvider.php
index 233252f282..2bf84a0200 100644
--- a/ProcessMaker/Providers/BroadcastServiceProvider.php
+++ b/ProcessMaker/Providers/BroadcastServiceProvider.php
@@ -15,6 +15,11 @@ class BroadcastServiceProvider extends ServiceProvider
public function boot()
{
Broadcast::routes(['middleware'=>['web', 'auth:anon']]);
+ Broadcast::routes([
+ 'middleware' => ['auth:api'],
+ 'prefix' => 'api',
+ ]);
+
require base_path('routes/channels.php');
}
}
diff --git a/ProcessMaker/Providers/EventServiceProvider.php b/ProcessMaker/Providers/EventServiceProvider.php
index 5e7a07ed53..9a6f0690df 100644
--- a/ProcessMaker/Providers/EventServiceProvider.php
+++ b/ProcessMaker/Providers/EventServiceProvider.php
@@ -3,16 +3,28 @@
namespace ProcessMaker\Providers;
use Illuminate\Foundation\Support\Providers\EventServiceProvider as ServiceProvider;
+use jdavidbakr\MailTracker\Events\ComplaintMessageEvent;
+use jdavidbakr\MailTracker\Events\EmailDeliveredEvent;
+use jdavidbakr\MailTracker\Events\EmailSentEvent;
+use jdavidbakr\MailTracker\Events\LinkClickedEvent;
+use jdavidbakr\MailTracker\Events\PermanentBouncedMessageEvent;
+use jdavidbakr\MailTracker\Events\ViewEmailEvent;
use ProcessMaker\Events\ActivityAssigned;
use ProcessMaker\Events\ActivityCompleted;
use ProcessMaker\Events\ActivityReassignment;
use ProcessMaker\Events\AuthClientCreated;
use ProcessMaker\Events\AuthClientDeleted;
use ProcessMaker\Events\AuthClientUpdated;
+use ProcessMaker\Events\BouncedEmail;
use ProcessMaker\Events\CategoryCreated;
use ProcessMaker\Events\CategoryDeleted;
use ProcessMaker\Events\CategoryUpdated;
use ProcessMaker\Events\CustomizeUiUpdated;
+use ProcessMaker\Events\EmailComplaint;
+use ProcessMaker\Events\EmailDelivered;
+use ProcessMaker\Events\EmailLinkClicked;
+use ProcessMaker\Events\EmailSent;
+use ProcessMaker\Events\EmailViewed;
use ProcessMaker\Events\EnvironmentVariablesCreated;
use ProcessMaker\Events\EnvironmentVariablesDeleted;
use ProcessMaker\Events\EnvironmentVariablesUpdated;
@@ -111,6 +123,25 @@ class EventServiceProvider extends ServiceProvider
TranslationChanged::class => [
InvalidateScreenCacheOnTranslationChange::class,
],
+ // Email Tracker
+ EmailSentEvent::class => [
+ EmailSent::class,
+ ],
+ ViewEmailEvent::class => [
+ EmailViewed::class,
+ ],
+ LinkClickedEvent::class => [
+ EmailLinkClicked::class,
+ ],
+ EmailDeliveredEvent::class => [
+ EmailDelivered::class,
+ ],
+ ComplaintMessageEvent::class => [
+ EmailComplaint::class,
+ ],
+ PermanentBouncedMessageEvent::class => [
+ BouncedEmail::class,
+ ],
];
/**
diff --git a/ProcessMaker/Traits/MakeHttpRequests.php b/ProcessMaker/Traits/MakeHttpRequests.php
index 26da4cecd3..53003e619b 100644
--- a/ProcessMaker/Traits/MakeHttpRequests.php
+++ b/ProcessMaker/Traits/MakeHttpRequests.php
@@ -27,6 +27,14 @@ trait MakeHttpRequests
'OAUTH2_PASSWORD' => 'passwordAuthorization',
];
+ private $debugData = [
+ 'method' => '',
+ 'url' => '',
+ 'headers' => [],
+ 'body' => '',
+ 'bodyType' => '',
+ ];
+
/**
* Verify certificate ssl
*
@@ -316,9 +324,12 @@ private function response($response, array $data = [], array $config = [])
$status = $response->getStatusCode();
$bodyContent = $response->getBody()->getContents();
if (!$this->isJson($bodyContent)) {
+ devtools($this->debugData['method'], $this->debugData['url'], $status, ['Response' => $bodyContent, 'Request' => $this->debugData['body']]);
return ['response' => $bodyContent, 'status' => $status];
}
+ devtools($this->debugData['method'], $this->debugData['url'], $status, ['Response' => $bodyContent, 'Request' => $this->debugData['body']]);
+
switch (true) {
case $status == 200:
$content = json_decode($bodyContent, true);
@@ -345,6 +356,7 @@ private function response($response, array $data = [], array $config = [])
}
}
+ devtools('', 'MAPPED RESPONSE', '', ['Output' => json_encode($mapped, JSON_PRETTY_PRINT)]);
return $mapped;
}
@@ -353,9 +365,12 @@ private function responseWithHeaderData($response, array $data = [], array $conf
$status = $response->getStatusCode();
$bodyContent = $response->getBody()->getContents();
if (!$this->isJson($bodyContent)) {
+ devtools($this->debugData['method'], $this->debugData['url'], $status, ['Response' => $bodyContent, 'Request' => $this->debugData['body']]);
return ['response' => $bodyContent, 'status' => $status];
}
+ devtools($this->debugData['method'], $this->debugData['url'], $status, ['Response' => $bodyContent, 'Request' => $this->debugData['body']]);
+
switch (true) {
case $status == 200:
$content = json_decode($bodyContent, true);
@@ -416,6 +431,7 @@ private function responseWithHeaderData($response, array $data = [], array $conf
$mapped[$processVar] = $evaluatedApiVar;
}
+ devtools('', 'MAPPED RESPONSE', '', ['Output' => json_encode($mapped, JSON_PRETTY_PRINT)]);
return $mapped;
}
@@ -436,7 +452,8 @@ private function call($method, $url, array $headers, $body, $bodyType)
{
$client = $this->client ?? app()->make(Client::class, [
'config' => [
- 'verify' => $this->verifySsl,
+ // Disable SSL verification in local development environment
+ 'verify' => $this->verifySsl && (config('app.env') !== 'local'),
'timeout' => $this->timeout,
],
]);
@@ -446,6 +463,11 @@ private function call($method, $url, array $headers, $body, $bodyType)
}
$request = new Request($method, $url, $headers, $body);
+ $this->debugData['method'] = $method;
+ $this->debugData['url'] = $url;
+ $this->debugData['headers'] = $headers;
+ $this->debugData['body'] = $body;
+ $this->debugData['bodyType'] = $bodyType;
if ($this->debug_mode) {
$this->log('Request: ', var_export(compact('method', 'url', 'body', 'bodyType'), true));
diff --git a/composer.json b/composer.json
index 907fe921eb..ac8f2eefa4 100644
--- a/composer.json
+++ b/composer.json
@@ -22,6 +22,7 @@
"google/apiclient": "^2.18",
"guzzlehttp/guzzle": "^7.9",
"igaster/laravel-theme": "^2.0",
+ "jdavidbakr/mail-tracker": "^7.18",
"jenssegers/agent": "^2.6",
"laravel/framework": "^11.0",
"laravel/horizon": "^5.30",
@@ -179,6 +180,7 @@
"package-webentry": "2.29.0",
"package-api-testing": "1.3.0",
"package-variable-finder": "1.0.3",
+ "package-private-equity": "dev-main",
"packages": "^0"
},
"docker-executors": {
diff --git a/composer.lock b/composer.lock
index 6b8bedc206..f83d9697e4 100644
--- a/composer.lock
+++ b/composer.lock
@@ -4,7 +4,7 @@
"Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies",
"This file is @generated automatically"
],
- "content-hash": "79f6d31afab1b6fd6e8e9cb5e0174daf",
+ "content-hash": "4390c170cc7fac64f61278f1b7d4dc48",
"packages": [
{
"name": "aws/aws-crt-php",
@@ -60,6 +60,65 @@
},
"time": "2024-10-18T22:15:13+00:00"
},
+ {
+ "name": "aws/aws-php-sns-message-validator",
+ "version": "1.9.1",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/aws/aws-php-sns-message-validator.git",
+ "reference": "80850e8d93fb57889ce609e113895dd2f1d7eed6"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/aws/aws-php-sns-message-validator/zipball/80850e8d93fb57889ce609e113895dd2f1d7eed6",
+ "reference": "80850e8d93fb57889ce609e113895dd2f1d7eed6",
+ "shasum": ""
+ },
+ "require": {
+ "ext-openssl": "*",
+ "php": ">=7.2.5",
+ "psr/http-message": "^1.0 || ^2.0"
+ },
+ "require-dev": {
+ "guzzlehttp/psr7": "^1.9.1 || ^2.4.5",
+ "phpunit/phpunit": "^5.6.3 || ^8.5 || ^9.5",
+ "squizlabs/php_codesniffer": "^2.3",
+ "yoast/phpunit-polyfills": "^1.0"
+ },
+ "type": "library",
+ "autoload": {
+ "psr-4": {
+ "Aws\\Sns\\": "src/"
+ }
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "Apache-2.0"
+ ],
+ "authors": [
+ {
+ "name": "Amazon Web Services",
+ "homepage": "http://aws.amazon.com"
+ }
+ ],
+ "description": "Amazon SNS message validation for PHP",
+ "homepage": "http://aws.amazon.com/sdkforphp",
+ "keywords": [
+ "SNS",
+ "amazon",
+ "aws",
+ "cloud",
+ "message",
+ "sdk",
+ "webhooks"
+ ],
+ "support": {
+ "forum": "https://forums.aws.amazon.com/forum.jspa?forumID=80",
+ "issues": "https://github.com/aws/aws-sns-message-validator/issues",
+ "source": "https://github.com/aws/aws-php-sns-message-validator/tree/1.9.1"
+ },
+ "time": "2025-02-25T22:19:51+00:00"
+ },
{
"name": "aws/aws-sdk-php",
"version": "3.337.3",
@@ -2721,6 +2780,72 @@
},
"time": "2025-02-06T18:54:20+00:00"
},
+ {
+ "name": "jdavidbakr/mail-tracker",
+ "version": "7.18",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/jdavidbakr/mail-tracker.git",
+ "reference": "1e5d135840769ad8573591e3619810b39da05bba"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/jdavidbakr/mail-tracker/zipball/1e5d135840769ad8573591e3619810b39da05bba",
+ "reference": "1e5d135840769ad8573591e3619810b39da05bba",
+ "shasum": ""
+ },
+ "require": {
+ "aws/aws-php-sns-message-validator": "^1.8",
+ "aws/aws-sdk-php": "^3.258",
+ "guzzlehttp/guzzle": "^7.2",
+ "illuminate/support": "^10.0|^11.0|^12.0",
+ "php": "^8.1"
+ },
+ "require-dev": {
+ "mockery/mockery": "^1.4.4",
+ "orchestra/testbench": "^8.0|^9.0|^10.0",
+ "phpunit/phpunit": "^9.5.10|^10.5|^11.5.3"
+ },
+ "suggest": {
+ "fedeisas/laravel-mail-css-inliner": "Automatically inlines CSS into all outgoing mail."
+ },
+ "type": "library",
+ "extra": {
+ "laravel": {
+ "providers": [
+ "jdavidbakr\\MailTracker\\MailTrackerServiceProvider"
+ ]
+ }
+ },
+ "autoload": {
+ "psr-4": {
+ "jdavidbakr\\MailTracker\\": "src"
+ }
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "MIT"
+ ],
+ "authors": [
+ {
+ "name": "J David Baker",
+ "email": "me@jdavidbaker.com",
+ "homepage": "http://www.jdavidbaker.com",
+ "role": "Developer"
+ }
+ ],
+ "description": "Logs and tracks all outgoing emails from Laravel",
+ "homepage": "https://github.com/jdavidbakr/MailTracker",
+ "keywords": [
+ "MailTracker",
+ "jdavidbakr"
+ ],
+ "support": {
+ "issues": "https://github.com/jdavidbakr/mail-tracker/issues",
+ "source": "https://github.com/jdavidbakr/mail-tracker/tree/7.18"
+ },
+ "time": "2025-02-25T17:58:11+00:00"
+ },
{
"name": "jenssegers/agent",
"version": "v2.6.4",
@@ -15846,6 +15971,6 @@
"platform": {
"php": "^8.3"
},
- "platform-dev": {},
+ "platform-dev": [],
"plugin-api-version": "2.6.0"
}
diff --git a/config/cors.php b/config/cors.php
index 8a39e6daa6..6d0570dac6 100644
--- a/config/cors.php
+++ b/config/cors.php
@@ -15,11 +15,15 @@
|
*/
- 'paths' => ['api/*', 'sanctum/csrf-cookie'],
+ 'paths' => ['api/*', 'sanctum/csrf-cookie', 'oauth/*'],
'allowed_methods' => ['*'],
- 'allowed_origins' => ['*'],
+ 'allowed_origins' => [
+ 'http://localhost:4200',
+ 'https://legendary-adventure-2n21ppv.pages.github.io',
+ 'https://processmaker.github.io',
+ ],
'allowed_origins_patterns' => [],
@@ -29,6 +33,6 @@
'max_age' => 0,
- 'supports_credentials' => false,
+ 'supports_credentials' => true,
];
diff --git a/config/horizon.php b/config/horizon.php
index 7b1a5f8d87..ab9e7e9dad 100644
--- a/config/horizon.php
+++ b/config/horizon.php
@@ -148,7 +148,7 @@
'balance' => env('PM4_HORIZON_SUPERVISOR_BPMN_BALANCE', 'simple'),
'tries' => env('PM4_HORIZON_SUPERVISOR_BPMN_TRIES', 3),
'timeout' => env('PM4_HORIZON_SUPERVISOR_BPMN_TIMEOUT', 3600),
- 'sleep' => intval(env('BPMN_QUEUE_INTERVAL', 3000)) * 0.001,
+ 'sleep' => intval(env('BPMN_QUEUE_INTERVAL', 1000)) * 0.001,
'minProcesses' => env('PM4_HORIZON_SUPERVISOR_BPMN_MIN_PROCESSES', 1),
'maxProcesses' => env('PM4_HORIZON_SUPERVISOR_BPMN_MAX_PROCESSES', 1),
],
@@ -170,7 +170,7 @@
'balance' => env('PM4_HORIZON_SUPERVISOR_BPMN_BALANCE', 'false'),
'tries' => env('PM4_HORIZON_SUPERVISOR_BPMN_TRIES', 3),
'timeout' => env('PM4_HORIZON_SUPERVISOR_BPMN_TIMEOUT', 3600),
- 'sleep' => intval(env('BPMN_QUEUE_INTERVAL', 3000)) * 0.001,
+ 'sleep' => intval(env('BPMN_QUEUE_INTERVAL', 1000)) * 0.001,
'minProcesses' => env('PM4_HORIZON_SUPERVISOR_BPMN_MIN_PROCESSES', 1),
'maxProcesses' => env('PM4_HORIZON_SUPERVISOR_BPMN_MAX_PROCESSES', 1),
],
@@ -192,7 +192,7 @@
'balance' => env('PM4_HORIZON_SUPERVISOR_BPMN_BALANCE', 'false'),
'tries' => env('PM4_HORIZON_SUPERVISOR_BPMN_TRIES', 3),
'timeout' => env('PM4_HORIZON_SUPERVISOR_BPMN_TIMEOUT', 3600),
- 'sleep' => intval(env('BPMN_QUEUE_INTERVAL', 3000)) * 0.001,
+ 'sleep' => intval(env('BPMN_QUEUE_INTERVAL', 1000)) * 0.001,
'minProcesses' => env('PM4_HORIZON_SUPERVISOR_BPMN_MIN_PROCESSES', 1),
'maxProcesses' => env('PM4_HORIZON_SUPERVISOR_BPMN_MAX_PROCESSES', 1),
],
diff --git a/config/mail-tracker.php b/config/mail-tracker.php
new file mode 100644
index 0000000000..595c4d93ca
--- /dev/null
+++ b/config/mail-tracker.php
@@ -0,0 +1,107 @@
+ true,
+
+ /**
+ * To disable injecting tracking links, set this to false.
+ */
+ 'track-links' => true,
+
+ /**
+ * Optionally expire old emails, set to 0 to keep forever.
+ */
+ 'expire-days' => 60,
+
+ /**
+ * Where should the pingback URL route be?
+ */
+ 'route' => [
+ 'prefix' => 'email',
+ 'middleware' => ['api'],
+ ],
+
+ /**
+ * If we get a link click without a URL, where should we send it to?
+ */
+ 'redirect-missing-links-to' => '/',
+
+ /**
+ * Where should the admin route be?
+ */
+ 'admin-route' => [
+ 'enabled' => true, // Should the admin routes be enabled?
+ 'prefix' => 'email-manager',
+ 'middleware' => [
+ 'web',
+ 'can:see-sent-emails'
+ ],
+ ],
+
+ /**
+ * Admin Template
+ * example
+ * 'name' => 'layouts.app' for Default emailTraking use 'emailTrakingViews::layouts.app'
+ * 'section' => 'content' for Default emailTraking use 'content'
+ * 'styles_section' => 'styles' for Default emailTraking use 'styles'
+ */
+ 'admin-template' => [
+ 'name' => 'emailTrakingViews::layouts.app',
+ 'section' => 'content',
+ ],
+
+ /**
+ * Number of emails per page in the admin view
+ */
+ 'emails-per-page' => 30,
+
+ /**
+ * Date Format
+ */
+ 'date-format' => 'Y-m-d H:i:s',
+
+ /**
+ * Default database connection name (optional - use null for default)
+ */
+ 'connection' => null,
+
+ /**
+ * The SNS notification topic - if set, discard all notifications not in this topic.
+ */
+ 'sns-topic' => null,
+
+ /**
+ * Determines whether the body of the email is logged in the sent_emails table
+ */
+ 'log-content' => true,
+
+ /**
+ * Determines whether the body should be stored in a file instead of database
+ * Can be either 'database' or 'filesystem'
+ */
+ 'log-content-strategy' => 'database',
+
+ /**
+ * What filesystem we use for storing content html files
+ */
+ 'tracker-filesystem' => null,
+ 'tracker-filesystem-folder' => 'mail-tracker',
+
+ /**
+ * What queue should we dispatch our tracking jobs to? Null will use the default queue.
+ */
+ 'tracker-queue' => null,
+
+ /**
+ * Size limit for content length stored in database
+ */
+ 'content-max-size' => 65535,
+
+ /**
+ * Length of time to default past email search - if set, will set the default past limit to the amount of days below (Ex: => 356)
+ */
+ 'search-date-start' => null,
+];
diff --git a/database/migrations/2025_04_17_005609_update_oauth_clients_secret_nullable.php b/database/migrations/2025_04_17_005609_update_oauth_clients_secret_nullable.php
new file mode 100644
index 0000000000..08e05d6987
--- /dev/null
+++ b/database/migrations/2025_04_17_005609_update_oauth_clients_secret_nullable.php
@@ -0,0 +1,27 @@
+string('secret', 100)->nullable()->change();
+ });
+ }
+
+ /**
+ * Reverse the migrations.
+ */
+ public function down(): void
+ {
+ Schema::table('oauth_clients', function (Blueprint $table) {
+ $table->string('secret', 100)->nullable(false)->change();
+ });
+ }
+};
diff --git a/database/processes/templates/IntermediateTimerEventFEEL.bpmn b/database/processes/templates/IntermediateTimerEventFEEL.bpmn
new file mode 100644
index 0000000000..097eb4f440
--- /dev/null
+++ b/database/processes/templates/IntermediateTimerEventFEEL.bpmn
@@ -0,0 +1,100 @@
+
+
+
+
+
+
+
+
+
+ _8
+
+
+
+ _8
+ _9
+
+
+ _9
+ _10
+
+
+ date ~ "T" ~ time
+
+
+
+ _10
+ _11
+
+
+
+
+
+
+ _11
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/helpers.php b/helpers.php
index 18d71f72e0..8ae1486ae3 100644
--- a/helpers.php
+++ b/helpers.php
@@ -1,6 +1,7 @@
$method,
+ 'url' => $url,
+ 'time' => date('Y-m-d H:i:s'),
+ 'status' => $status,
+ 'details' => $details,
+ ];
+
+ Cache::put($key, $entries, 60 * 5);
+}
diff --git a/resources/stubs/api2typescript/api-index.blade.php b/resources/stubs/api2typescript/api-index.blade.php
new file mode 100644
index 0000000000..565d644764
--- /dev/null
+++ b/resources/stubs/api2typescript/api-index.blade.php
@@ -0,0 +1,9 @@
+@foreach ($apiClasses as $class)
+import { {{ $class['className'] }} } from './{{ $class['tagLower'] }}.api';
+@endforeach
+
+export {
+@foreach ($apiClasses as $class)
+ {{ $class['className'] }},
+@endforeach
+};
\ No newline at end of file
diff --git a/resources/stubs/api2typescript/api-response.blade.php b/resources/stubs/api2typescript/api-response.blade.php
new file mode 100644
index 0000000000..94f8936f7f
--- /dev/null
+++ b/resources/stubs/api2typescript/api-response.blade.php
@@ -0,0 +1,7 @@
+export interface ApiResponse {
+ data?: T;
+ status?: number;
+ statusText?: string;
+ error?: string;
+ message?: string;
+}
diff --git a/resources/stubs/api2typescript/api-spec.blade.php b/resources/stubs/api2typescript/api-spec.blade.php
new file mode 100644
index 0000000000..fcbd47fc20
--- /dev/null
+++ b/resources/stubs/api2typescript/api-spec.blade.php
@@ -0,0 +1,37 @@
+import { {{ $className }} } from './{{ $tagLower }}.api';
+
+describe('{{ $className }}', () => {
+ // Mock API client
+ const mockApiClient = {
+ head: vi.fn(),
+ get: vi.fn(),
+ post: vi.fn(),
+ put: vi.fn(),
+ delete: vi.fn(),
+ patch: vi.fn(),
+ };
+
+ // Create instance
+ let api: {{ $className }};
+
+ beforeEach(() => {
+ api = new {{ $className }}(mockApiClient);
+ vi.resetAllMocks();
+ });
+
+@foreach ($methods as $method)
+
+ describe('{{ $method['methodName'] }}', () => {
+ it('{{ $method['summary'] }}', async () => {
+ const mockResponse = {!! $helper->json($helper->mockResponse($method), 6) !!};
+ mockApiClient.{{ $method['httpMethod'] }}.mockResolvedValue(mockResponse);
+
+ const result = await api.{{ $method['methodName'] }}({!! $helper->mockParams($method) !!});
+
+ expect(mockApiClient.{{ $method['httpMethod'] }}).toHaveBeenCalledWith({!! $helper->mockUrl($method) !!});
+ expect(result).toEqual(mockResponse);
+ });
+ });
+
+@endforeach
+});
diff --git a/resources/stubs/api2typescript/api.blade.php b/resources/stubs/api2typescript/api.blade.php
new file mode 100644
index 0000000000..ec4972cd80
--- /dev/null
+++ b/resources/stubs/api2typescript/api.blade.php
@@ -0,0 +1,69 @@
+@if (!empty($imports))
+import {
+@foreach ($imports as $import)
+ {{ $import }},
+@endforeach
+} from '../types/types';
+@endif
+
+export class {{ $className }} {
+ constructor(private apiClient: {
+ head: (endpoint: string) => Promise;
+ get: (endpoint: string) => Promise;
+ post: (endpoint: string, data: Record) => Promise;
+ put: (endpoint: string, data: Record) => Promise;
+ delete: (endpoint: string) => Promise;
+ patch: (endpoint: string, data: Record) => Promise;
+ }) {}
+
+@foreach ($methods as $method)
+ /**
+ * {{ $method['summary'] }}
+ */
+ {!! $method['methodName'] !!}({!! implode(', ', $method['paramList']) !!}): Promise<{!! $method['returnType'] ?: 'void' !!}> {
+@if (!empty($method['queryParams']))
+ const queryParams = new URLSearchParams();
+
+ if (params) {
+@foreach ($method['queryParams'] as $param)
+@php
+$paramName = Illuminate\Support\Str::camel($param['name']);
+$paramType = $helper->getTypescriptType($param);
+if ($paramType === 'boolean') {
+ $paramValue = "params.{$paramName} ? '1' : '0'";
+} elseif ($paramType === 'integer' || $paramType === 'number') {
+ $paramValue = "String(params.{$paramName})";
+} elseif ($paramType === 'array' || $paramType === 'string[]') {
+ $paramValue = "params.{$paramName}.join(',')";
+} elseif ($paramType === 'string') {
+ $paramValue = "params.{$paramName}";
+} else {
+ $paramValue = "JSON.stringify(params.{$paramName})";
+}
+@endphp
+ if (params.{{ $paramName }}) queryParams.append('{{ $param['name'] }}', {!! $paramValue !!}); // {!! $paramType !!}
+@endforeach
+ }
+
+ const queryString = queryParams.toString() ? `?${queryParams.toString()}` : '';
+@endif
+
+@if ($method['httpMethod'] === 'get' || $method['httpMethod'] === 'head')
+@if (!empty($method['queryParams']))
+ return this.apiClient.{{ $method['httpMethod'] }}<{!! $method['returnType'] ?: 'void' !!}>(`{{ $method['apiPath'] }}${queryString}`);
+@else
+ return this.apiClient.{{ $method['httpMethod'] }}<{!! $method['returnType'] ?: 'void' !!}>(`{{ $method['apiPath'] }}`);
+@endif
+@elseif ($method['httpMethod'] === 'post' ||$method['httpMethod'] === 'put' || $method['httpMethod'] === 'patch')
+@if (!empty($method['queryParams']))
+ return this.apiClient.{{$method['httpMethod']}}<{!! $method['returnType'] ?: 'void' !!}>(`{{ $method['apiPath'] }}${queryString}`, data as unknown as Record);
+@else
+ return this.apiClient.{{$method['httpMethod']}}<{!! $method['returnType'] ?: 'void' !!}>(`{{ $method['apiPath'] }}`, data as unknown as Record);
+@endif
+@elseif ($method['httpMethod'] === 'delete')
+ return this.apiClient.delete<{!! $method['returnType'] ?: 'void' !!}>(`{{ $method['apiPath'] }}`);
+@endif
+ }
+
+@endforeach
+}
diff --git a/resources/stubs/api2typescript/composable.blade.php b/resources/stubs/api2typescript/composable.blade.php
new file mode 100644
index 0000000000..eb2d32ce01
--- /dev/null
+++ b/resources/stubs/api2typescript/composable.blade.php
@@ -0,0 +1,23 @@
+/* eslint-disable @typescript-eslint/no-explicit-any */
+import { {{ $className }} } from '../api/{{ $tagLower }}.api';
+
+/**
+ * Hook to access ProcessMaker {{ ucfirst($tagLower) }} API
+ * @param apiClient - API client with authentication handling
+ * @returns {{ $className }} instance
+ */
+export const {{ $hookName }} = (apiClient: {
+ head: (endpoint: string) => Promise;
+ // eslint-disable-next-line @typescript-eslint/no-unused-vars
+ get: (endpoint: string) => Promise;
+ // eslint-disable-next-line @typescript-eslint/no-unused-vars
+ post: (endpoint: string, data: Record) => Promise;
+ // eslint-disable-next-line @typescript-eslint/no-unused-vars
+ put: (endpoint: string, data: Record) => Promise;
+ // eslint-disable-next-line @typescript-eslint/no-unused-vars
+ delete: (endpoint: string) => Promise;
+ // eslint-disable-next-line @typescript-eslint/no-unused-vars
+ patch: (endpoint: string, data: Record) => Promise;
+}) => {
+ return new {{ $className }}(apiClient);
+};
diff --git a/resources/stubs/api2typescript/composables-index.blade.php b/resources/stubs/api2typescript/composables-index.blade.php
new file mode 100644
index 0000000000..65423275ed
--- /dev/null
+++ b/resources/stubs/api2typescript/composables-index.blade.php
@@ -0,0 +1,9 @@
+@foreach ($hooks as $hook)
+import { {{ $hook }} } from './{{ $hook }}';
+@endforeach
+
+export {
+@foreach ($hooks as $hook)
+ {{ $hook }},
+@endforeach
+};
diff --git a/resources/stubs/api2typescript/main-index.blade.php b/resources/stubs/api2typescript/main-index.blade.php
new file mode 100644
index 0000000000..fb1cae5fa9
--- /dev/null
+++ b/resources/stubs/api2typescript/main-index.blade.php
@@ -0,0 +1,6 @@
+// Generated ProcessMaker SDK
+export * from './lib/processmaker-sdk'
+export * from './composables';
+export * from './engine';
+export * from './types/types';
+export * from './api';
diff --git a/resources/stubs/api2typescript/readme.blade.php b/resources/stubs/api2typescript/readme.blade.php
new file mode 100644
index 0000000000..dfd538da67
--- /dev/null
+++ b/resources/stubs/api2typescript/readme.blade.php
@@ -0,0 +1,45 @@
+# ProcessMaker SDK
+
+This SDK provides typed access to the ProcessMaker API.
+
+## Features
+
+- Fully typed API interfaces
+- Composable hooks for easy integration
+@foreach ($tags as $tag)
+- Complete implementation of the ProcessMaker {{ ucfirst(strtolower($tag)) }} API
+@endforeach
+
+## Usage
+
+@if ($firstTag)
+### {{ ucfirst(strtolower($firstTag)) }} API
+
+```typescript
+import { useProcessMakerApi } from '~/composables/useProcessMakerApi';
+import { useProcessMaker{{ ucfirst(strtolower($firstTag)) }} } from 'shared';
+
+// In your component or service
+const api = useProcessMakerApi();
+const {{ strtolower($firstTag) }}Api = useProcessMaker{{ ucfirst(strtolower($firstTag)) }}(api);
+
+// Example: Get all {{ strtolower($firstTag) }}
+const get{{ ucfirst(strtolower($firstTag)) }} = async () => {
+ try {
+ const response = await {{ strtolower($firstTag) }}Api.get{{ ucfirst(strtolower($firstTag)) }}();
+ return response.data;
+ } catch (error) {
+ console.error('Error fetching {{ strtolower($firstTag) }}:', error);
+ throw error;
+ }
+};
+```
+@endif
+
+## Available APIs
+
+Currently, the SDK includes:
+
+@foreach ($tags as $tag)
+- **{{ ucfirst(strtolower($tag)) }} API**: Complete implementation of the ProcessMaker {{ ucfirst(strtolower($tag)) }} API
+@endforeach
diff --git a/resources/stubs/api2typescript/types.blade.php b/resources/stubs/api2typescript/types.blade.php
new file mode 100644
index 0000000000..fc7c32125c
--- /dev/null
+++ b/resources/stubs/api2typescript/types.blade.php
@@ -0,0 +1,10 @@
+/* eslint-disable @typescript-eslint/no-explicit-any */
+@foreach ($interfaces as $interface)
+{!! $interface !!}
+
+@endforeach
+
+@foreach ($queryParamInterfaces as $interface)
+{!! $interface !!}
+
+@endforeach
diff --git a/resources/views/vendor/emailTrakingViews/emails/mensaje.blade.php b/resources/views/vendor/emailTrakingViews/emails/mensaje.blade.php
new file mode 100644
index 0000000000..1e4dd69edc
--- /dev/null
+++ b/resources/views/vendor/emailTrakingViews/emails/mensaje.blade.php
@@ -0,0 +1,30 @@
+@extends('emailTrakingViews::emails/mensaje_layout')
+@section('title')
+ Message from {{config('mail-tracker.name')}}
+@endsection
+
+@section('preheader')
+ Message from {{config('mail-tracker.name')}}
+@endsection
+@section('nombre_destinatario')
+ {{ $data['name'] }}
+@endsection
+@section('mensaje')
+ Static Email Title
+
+ Static Email Content
+
+ {{ $data['message'] }}
+@endsection
+@section('href_call_to_action')
+ {{env('APP_URL')}}
+@endsection
+@section('txt_call_to_action')
+ Call To Action
+@endsection
+@section('txt_extra')
+ This email comes from {{config('mail-tracker.name')}}
+@endsection
+@section('saludo_final')
+ Regards
+@endsection
diff --git a/resources/views/vendor/emailTrakingViews/emails/mensaje_layout.blade.php b/resources/views/vendor/emailTrakingViews/emails/mensaje_layout.blade.php
new file mode 100644
index 0000000000..1d1f0c4259
--- /dev/null
+++ b/resources/views/vendor/emailTrakingViews/emails/mensaje_layout.blade.php
@@ -0,0 +1,195 @@
+
+
+
+
+
+ @yield('title')
+
+
+
+
+
+
diff --git a/resources/views/vendor/emailTrakingViews/index.blade.php b/resources/views/vendor/emailTrakingViews/index.blade.php
new file mode 100644
index 0000000000..5de646dcce
--- /dev/null
+++ b/resources/views/vendor/emailTrakingViews/index.blade.php
@@ -0,0 +1,112 @@
+@extends(config('mail-tracker.admin-template.name'))
+@section(config('mail-tracker.admin-template.section'))
+
+
+
+
+
+ SNS Endpoint: {{ route('mailTracker_SNS') }}
+
+
+
+
+
+
+
+
+ | SMTP |
+ Recipient |
+ Subject |
+ First View |
+ Opens |
+ First Click |
+ Clicks |
+ Sent At |
+ View Email |
+ Click Report |
+
+ @foreach($emails as $email)
+
+ |
+
+ {{ Str::limit($email->smtp_info, 20) }}
+
+ |
+ {{$email->recipient}} |
+ {{$email->subject}} |
+ {{$email->opened_at}} |
+ {{$email->opens}} |
+ {{$email->clicked_at}} |
+ {{$email->clicks}} |
+ {{$email->created_at->format(config('mail-tracker.date-format'))}} |
+
+
+ View
+
+ |
+
+ @if($email->clicks > 0)
+ Url Report
+ @else
+ No Clicks
+ @endif
+ |
+
+ @endforeach
+
+
+
+
+
+ {!! $emails->render() !!}
+
+
+
+@endsection
diff --git a/resources/views/vendor/emailTrakingViews/layouts/app.blade.php b/resources/views/vendor/emailTrakingViews/layouts/app.blade.php
new file mode 100644
index 0000000000..9d55d24bb7
--- /dev/null
+++ b/resources/views/vendor/emailTrakingViews/layouts/app.blade.php
@@ -0,0 +1,13 @@
+
+
+
+
+
+
+ Mail Tracker
+
+
+
+ @yield('content')
+
+
\ No newline at end of file
diff --git a/resources/views/vendor/emailTrakingViews/show.blade.php b/resources/views/vendor/emailTrakingViews/show.blade.php
new file mode 100644
index 0000000000..9c4e553dc5
--- /dev/null
+++ b/resources/views/vendor/emailTrakingViews/show.blade.php
@@ -0,0 +1 @@
+{!!$email->content!!}
diff --git a/resources/views/vendor/emailTrakingViews/smtp_detail.blade.php b/resources/views/vendor/emailTrakingViews/smtp_detail.blade.php
new file mode 100644
index 0000000000..2989f94107
--- /dev/null
+++ b/resources/views/vendor/emailTrakingViews/smtp_detail.blade.php
@@ -0,0 +1,33 @@
+@extends(config('mail-tracker.admin-template.name'))
+@section(config('mail-tracker.admin-template.section'))
+
+
+
+
+
+ Recipient: {{$details->recipient}}
+ Subject: {{$details->subject}}
+ Sent At: {{$details->created_at->format(config('mail-tracker.date-format'))}}
+ SMTP Details: {{ $details->smtp_info }}
+
+
+
+@endsection
diff --git a/resources/views/vendor/emailTrakingViews/url_detail.blade.php b/resources/views/vendor/emailTrakingViews/url_detail.blade.php
new file mode 100644
index 0000000000..45e3449a39
--- /dev/null
+++ b/resources/views/vendor/emailTrakingViews/url_detail.blade.php
@@ -0,0 +1,50 @@
+@extends(config('mail-tracker.admin-template.name'))
+@section(config('mail-tracker.admin-template.section'))
+
+
+
+
+
+ Clicked URLs for Email ID {{$details->first()->email->id}}
+
+
+ View Message
+
+
+
+
+
+ Recipient: {{$details->first()->email->recipient}}
+ Subject: {{$details->first()->email->subject}}
+ Sent At: {{$details->first()->email->created_at->format(config('mail-tracker.date-format'))}}
+
+
+
+
+
+ | Url |
+ Clicks |
+ First Click At |
+ Last Click At |
+ @foreach($details as $detail)
+
+ | {{$detail->url}} |
+ {{$detail->clicks}} |
+ {{$detail->created_at->format(config('mail-tracker.date-format'))}} |
+ {{$detail->updated_at->format(config('mail-tracker.date-format'))}} |
+
+ @endforeach
+
+
+
+
+@endsection
diff --git a/routes/api.php b/routes/api.php
index 1d48e244e3..19e84ccde0 100644
--- a/routes/api.php
+++ b/routes/api.php
@@ -60,6 +60,8 @@
Route::put('users/update_language', [UserController::class, 'updateLanguage'])->name('users.updateLanguage');
Route::get('users_task_count', [UserController::class, 'getUsersTaskCount'])->name('users.users_task_count')
->middleware('can:view-users');
+ Route::get('users/current', [UserController::class, 'current'])->name('users.current');
+ Route::post('users/logout', [UserController::class, 'logout'])->name('users.logout');
// User Groups
Route::put('users/{user}/groups', [UserController::class, 'updateGroups'])->name('users.groups.update')->middleware('can:edit-users');
@@ -240,7 +242,12 @@
Route::put('requests/{request}/retry', [ProcessRequestController::class, 'retry'])->name('requests.retry')->middleware('can:update,request');
Route::delete('requests/{request}', [ProcessRequestController::class, 'destroy'])->name('requests.destroy')->middleware('can:destroy,request');
Route::get('requests/{request}/tokens', [ProcessRequestController::class, 'getRequestToken'])->name('requests.getRequestToken')->middleware('can:view,request');
- Route::post('requests/{request}/events/{event}', [ProcessRequestController::class, 'activateIntermediateEvent'])->name('requests.update,request');
+ Route::post('requests/{request}/events/{event}', [ProcessRequestController::class, 'activateIntermediateEvent'])
+ ->name('requests.update,request')
+ ->where('event', '[a-zA-Z0-9_\-\.]+');
+ Route::post('requests/{request}/boundary/{boundary_event}', [ProcessRequestController::class, 'triggerBoundaryEvent'])
+ ->name('requests.triggerBoundaryEvent')
+ ->where('boundary_event', '[a-zA-Z0-9_\-\.]+');
Route::get('requests/{request}/details-screen-request', [ProcessRequestController::class, 'screenRequested'])->name('requests.detail.screen')->middleware('can:view,request');
Route::get('requests/{request}/end-event-destination', [ProcessRequestController::class, 'endEventDestination'])->name('requests.end_event_destination')->middleware('can:view,request');
diff --git a/routes/channels.php b/routes/channels.php
index eb10a61a18..b3fdd35369 100644
--- a/routes/channels.php
+++ b/routes/channels.php
@@ -33,6 +33,22 @@
|| $request->process?->manager_id === $user->id;
});
+Broadcast::channel('ProcessMaker.Models.ProcessRequest.{id}.SubProcesses', function ($user, $id) {
+ if ($id === 'undefined' || $user === 'undefined') {
+ return;
+ }
+
+ if ($user->is_administrator) {
+ return true;
+ }
+
+ $request = ProcessRequest::find($id);
+
+ return $request->user_id === $user->id
+ || !empty($request->participants()->where('users.id', $user->getKey())->first())
+ || $request->process?->manager_id === $user->id;
+});
+
Broadcast::channel('ProcessMaker.Models.ProcessRequestToken.{id}', function ($user, $id) {
if ($user->is_administrator) {
return true;
diff --git a/storage/api-docs/api-docs.json b/storage/api-docs/api-docs.json
index 3755004f8f..9373a2878e 100644
--- a/storage/api-docs/api-docs.json
+++ b/storage/api-docs/api-docs.json
@@ -18,14 +18,14 @@
}
],
"paths": {
- "/collections": {
+ "/decision_table_categories": {
"get": {
"tags": [
- "Collections"
+ "DecisionTableCategories"
],
- "summary": "Returns all collections that the user has access to",
- "description": "Get a list of Collections.",
- "operationId": "getCollections",
+ "summary": "Returns all Decision Tables categories that the user has access to",
+ "description": "Display a listing of the Decision Tables Categories.",
+ "operationId": "getDecisionTableCategories",
"parameters": [
{
"$ref": "#/components/parameters/filter"
@@ -38,14 +38,11 @@
},
{
"$ref": "#/components/parameters/per_page"
- },
- {
- "$ref": "#/components/parameters/include"
}
],
"responses": {
"200": {
- "description": "list of collections",
+ "description": "list of Decision Tables categories",
"content": {
"application/json": {
"schema": {
@@ -53,11 +50,16 @@
"data": {
"type": "array",
"items": {
- "$ref": "#/components/schemas/collections"
+ "$ref": "#/components/schemas/DecisionTableCategory"
}
},
"meta": {
- "$ref": "#/components/schemas/metadata"
+ "type": "object",
+ "allOf": [
+ {
+ "$ref": "#/components/schemas/metadata"
+ }
+ ]
}
},
"type": "object"
@@ -69,17 +71,17 @@
},
"post": {
"tags": [
- "Collections"
+ "DecisionTableCategories"
],
- "summary": "Save a new collections",
- "description": "Create a new Collection.",
- "operationId": "createCollection",
+ "summary": "Save a new Decision Table Category",
+ "description": "Store a newly created Decision Tables Category in storage",
+ "operationId": "createDecisionTableCategory",
"requestBody": {
"required": true,
"content": {
"application/json": {
"schema": {
- "$ref": "#/components/schemas/collectionsEditable"
+ "$ref": "#/components/schemas/decisionTableCategoryEditable"
}
}
}
@@ -90,7 +92,7 @@
"content": {
"application/json": {
"schema": {
- "$ref": "#/components/schemas/collections"
+ "$ref": "#/components/schemas/DecisionTableCategory"
}
}
}
@@ -98,19 +100,19 @@
}
}
},
- "/collections/{collection_id}": {
+ "/decision_table_categories/{decision_table_categories_id}": {
"get": {
"tags": [
- "Collections"
+ "DecisionTableCategories"
],
- "summary": "Get single collections by ID",
- "description": "Get a single Collection.",
- "operationId": "getCollectionById",
+ "summary": "Get single Decision Table category by ID",
+ "description": "Display the specified decision Tables category.",
+ "operationId": "getDecisionTableCategoryById",
"parameters": [
{
- "name": "collection_id",
+ "name": "decision_table_categories_id",
"in": "path",
- "description": "ID of collection to return",
+ "description": "ID of Decision Table category to return",
"required": true,
"schema": {
"type": "string"
@@ -119,11 +121,11 @@
],
"responses": {
"200": {
- "description": "Successfully found the collections",
+ "description": "Successfully found the Decision Table",
"content": {
"application/json": {
"schema": {
- "$ref": "#/components/schemas/collections"
+ "$ref": "#/components/schemas/DecisionTableCategory"
}
}
}
@@ -132,16 +134,16 @@
},
"put": {
"tags": [
- "Collections"
+ "DecisionTableCategories"
],
- "summary": "Update a collection",
- "description": "Update a Collection.",
- "operationId": "updateCollection",
+ "summary": "Update a Decision Table Category",
+ "description": "Updates the current element",
+ "operationId": "updateDecisionTableCategory",
"parameters": [
{
- "name": "collection_id",
+ "name": "decision_table_categories_id",
"in": "path",
- "description": "ID of collection to update",
+ "description": "ID of Decision Table category to return",
"required": true,
"schema": {
"type": "string"
@@ -153,126 +155,36 @@
"content": {
"application/json": {
"schema": {
- "$ref": "#/components/schemas/collectionsEditable"
- }
- }
- }
- },
- "responses": {
- "204": {
- "description": "success"
- }
- }
- },
- "delete": {
- "tags": [
- "Collections"
- ],
- "summary": "Delete a collection",
- "description": "Delete a Collection.",
- "operationId": "deleteCollection",
- "parameters": [
- {
- "name": "collection_id",
- "in": "path",
- "description": "ID of collection to return",
- "required": true,
- "schema": {
- "type": "string"
- }
- }
- ],
- "responses": {
- "204": {
- "description": "success"
- }
- }
- }
- },
- "/collections/{collection_id}/export": {
- "post": {
- "tags": [
- "Screens"
- ],
- "summary": "Trigger export collections job",
- "description": "Export the specified collection.",
- "operationId": "exportCollection",
- "parameters": [
- {
- "name": "collection_id",
- "in": "path",
- "description": "ID of the collection to export",
- "required": true,
- "schema": {
- "type": "string"
- }
- }
- ],
- "responses": {
- "202": {
- "description": "success"
- }
- }
- }
- },
- "/collections/import": {
- "post": {
- "tags": [
- "Collections"
- ],
- "summary": "Import a new collection",
- "description": "Import the specified collection.",
- "operationId": "importCollection",
- "requestBody": {
- "required": true,
- "content": {
- "multipart/form-data": {
- "schema": {
- "required": [
- "file"
- ],
- "properties": {
- "file": {
- "description": "file to upload",
- "type": "file",
- "format": "file"
- }
- },
- "type": "object"
+ "$ref": "#/components/schemas/decisionTableCategoryEditable"
}
}
}
},
"responses": {
- "201": {
+ "200": {
"description": "success",
"content": {
"application/json": {
"schema": {
- "$ref": "#/components/schemas/collections"
+ "$ref": "#/components/schemas/DecisionTableCategory"
}
}
}
- },
- "200": {
- "description": "success"
}
}
- }
- },
- "/collections/{collection_id}/truncate": {
+ },
"delete": {
"tags": [
- "Collections"
+ "DecisionTableCategories"
],
- "summary": "Deletes all records in a collection",
- "description": "Truncate a Collection.",
- "operationId": "truncateCollection",
+ "summary": "Delete a Decision Table category",
+ "description": "Remove the specified resource from storage.",
+ "operationId": "deleteDecisionTableCategory",
"parameters": [
{
- "name": "collection_id",
+ "name": "decision_table_categories_id",
"in": "path",
- "description": "ID of collection to truncate",
+ "description": "ID of Decision Table category to return",
"required": true,
"schema": {
"type": "string"
@@ -286,34 +198,15 @@
}
}
},
- "/collections/{collection_id}/records": {
+ "/decision_tables": {
"get": {
"tags": [
- "Collections"
+ "DecisionTables"
],
- "summary": "Returns all records",
- "description": "Get the list of records of a collection.",
- "operationId": "getRecords",
+ "summary": "Returns all Decision tables that the user has access to",
+ "description": "Display a listing of the resource.",
+ "operationId": "getDecisionTables",
"parameters": [
- {
- "name": "collection_id",
- "in": "path",
- "description": "ID of collection to get records for",
- "required": true,
- "schema": {
- "type": "string"
- }
- },
- {
- "name": "pmql",
- "in": "query",
- "schema": {
- "type": "string"
- }
- },
- {
- "$ref": "#/components/parameters/per_page"
- },
{
"$ref": "#/components/parameters/filter"
},
@@ -323,13 +216,16 @@
{
"$ref": "#/components/parameters/order_direction"
},
+ {
+ "$ref": "#/components/parameters/per_page"
+ },
{
"$ref": "#/components/parameters/include"
}
],
"responses": {
"200": {
- "description": "list of records of a collection",
+ "description": "list of Decision Tables",
"content": {
"application/json": {
"schema": {
@@ -337,11 +233,16 @@
"data": {
"type": "array",
"items": {
- "$ref": "#/components/schemas/records"
+ "$ref": "#/components/schemas/decisionTable"
}
},
"meta": {
- "$ref": "#/components/schemas/metadata"
+ "type": "object",
+ "allOf": [
+ {
+ "$ref": "#/components/schemas/metadata"
+ }
+ ]
}
},
"type": "object"
@@ -353,28 +254,17 @@
},
"post": {
"tags": [
- "Collections"
- ],
- "summary": "Save a new record in a collection",
- "description": "Create a new record in a Collection.",
- "operationId": "createRecord",
- "parameters": [
- {
- "name": "collection_id",
- "in": "path",
- "description": "ID of the collection",
- "required": true,
- "schema": {
- "type": "string"
- }
- }
+ "DecisionTables"
],
+ "summary": "Save a new Decision Table",
+ "description": "Store a newly created resource in storage.",
+ "operationId": "createDecisionTable",
"requestBody": {
"required": true,
"content": {
"application/json": {
"schema": {
- "$ref": "#/components/schemas/recordsEditable"
+ "$ref": "#/components/schemas/decisionTableEditable"
}
}
}
@@ -385,7 +275,7 @@
"content": {
"application/json": {
"schema": {
- "$ref": "#/components/schemas/records"
+ "$ref": "#/components/schemas/decisionTable"
}
}
}
@@ -393,28 +283,19 @@
}
}
},
- "/collections/{collection_id}/records/{record_id}": {
+ "/decision_tables/{decision_table_id}": {
"get": {
"tags": [
- "Collections"
+ "DecisionTables"
],
- "summary": "Get single record of a collection",
- "description": "Get a single record of a Collection.",
- "operationId": "getRecordById",
+ "summary": "Get single Decision Table by ID",
+ "description": "Display the specified resource.",
+ "operationId": "getDecisionTableById",
"parameters": [
{
- "name": "collection_id",
- "in": "path",
- "description": "ID of the collection",
- "required": true,
- "schema": {
- "type": "string"
- }
- },
- {
- "name": "record_id",
+ "name": "decision_table_id",
"in": "path",
- "description": "ID of the record to return",
+ "description": "ID of Decision Table to return",
"required": true,
"schema": {
"type": "string"
@@ -423,11 +304,11 @@
],
"responses": {
"200": {
- "description": "Successfully found the record",
+ "description": "Successfully found the Decision Table",
"content": {
"application/json": {
"schema": {
- "$ref": "#/components/schemas/records"
+ "$ref": "#/components/schemas/decisionTable"
}
}
}
@@ -436,25 +317,16 @@
},
"put": {
"tags": [
- "Collections"
+ "DecisionTables"
],
- "summary": "Update a record",
- "description": "Update a record in a Collection.",
- "operationId": "updateRecord",
+ "summary": "Update a Decision Table",
+ "description": "Update a Decision table",
+ "operationId": "updateDecisionTable",
"parameters": [
{
- "name": "collection_id",
- "in": "path",
- "description": "ID of collection",
- "required": true,
- "schema": {
- "type": "string"
- }
- },
- {
- "name": "record_id",
+ "name": "decision_table_id",
"in": "path",
- "description": "ID of the record ",
+ "description": "ID of Decision Table to return",
"required": true,
"schema": {
"type": "string"
@@ -466,38 +338,36 @@
"content": {
"application/json": {
"schema": {
- "$ref": "#/components/schemas/recordsEditable"
+ "$ref": "#/components/schemas/decisionTableEditable"
}
}
}
},
"responses": {
"204": {
- "description": "success"
+ "description": "success",
+ "content": {
+ "application/json": {
+ "schema": {
+ "$ref": "#/components/schemas/decisionTable"
+ }
+ }
+ }
}
}
},
"delete": {
"tags": [
- "Collections"
+ "DecisionTables"
],
- "summary": "Delete a collection record",
- "description": "Delete a record of a Collection.",
- "operationId": "deleteRecord",
+ "summary": "Delete a Decision Table",
+ "description": "Delete a Decision tables",
+ "operationId": "deleteDecisionTable",
"parameters": [
{
- "name": "collection_id",
- "in": "path",
- "description": "ID of collection",
- "required": true,
- "schema": {
- "type": "string"
- }
- },
- {
- "name": "record_id",
+ "name": "decision_table_id",
"in": "path",
- "description": "ID of record in collection",
+ "description": "ID of Decision Table to return",
"required": true,
"schema": {
"type": "string"
@@ -506,31 +376,74 @@
],
"responses": {
"204": {
- "description": "success"
+ "description": "success",
+ "content": {
+ "application/json": {
+ "schema": {
+ "$ref": "#/components/schemas/decisionTable"
+ }
+ }
+ }
}
}
- },
- "patch": {
+ }
+ },
+ "/decision_tables/{decision_table_id}/duplicate": {
+ "put": {
"tags": [
- "Collections"
+ "DecisionTables"
],
- "summary": "Partial update of a record",
- "description": "Implements a partial update of a record in a Collection.",
- "operationId": "patchRecord",
+ "summary": "duplicate a Decision Table",
+ "description": "duplicate a Decision table.",
+ "operationId": "duplicateDecisionTable",
"parameters": [
{
- "name": "collection_id",
+ "name": "decision_table_id",
"in": "path",
- "description": "ID of collection ",
+ "description": "ID of Decision Table to return",
"required": true,
"schema": {
"type": "string"
}
- },
+ }
+ ],
+ "requestBody": {
+ "required": true,
+ "content": {
+ "application/json": {
+ "schema": {
+ "$ref": "#/components/schemas/decisionTableEditable"
+ }
+ }
+ }
+ },
+ "responses": {
+ "201": {
+ "description": "success",
+ "content": {
+ "application/json": {
+ "schema": {
+ "$ref": "#/components/schemas/decisionTable"
+ }
+ }
+ }
+ }
+ }
+ }
+ },
+ "/decision_tables/{decision_table_id}/excel-import": {
+ "post": {
+ "tags": [
+ "DecisionTables"
+ ],
+ "summary": "Import a new decision table",
+ "description": "Import a Decision table from excel",
+ "operationId": "importExcel",
+ "parameters": [
{
- "name": "record_id",
+ "name": "decision_table_id",
"in": "path",
- "description": "ID of the record ",
+ "description": "ID of Decision Table to return",
"required": true,
"schema": {
"type": "string"
@@ -540,16 +453,143 @@
"requestBody": {
"required": true,
"content": {
- "application/json": {
+ "multipart/form-data": {
"schema": {
- "$ref": "#/components/schemas/collectionsEditable"
+ "properties": {
+ "file": {
+ "description": "file to import",
+ "type": "string",
+ "format": "binary"
+ }
+ },
+ "type": "object"
}
}
}
},
+ "responses": {
+ "201": {
+ "description": "success",
+ "content": {
+ "application/json": {
+ "schema": {
+ "properties": {
+ "status": {
+ "type": "object"
+ }
+ },
+ "type": "object"
+ }
+ }
+ }
+ }
+ }
+ }
+ },
+ "/decision_tables/{decision_table_id}/export": {
+ "post": {
+ "tags": [
+ "DecisionTables"
+ ],
+ "summary": "Export a single Decision Table by ID",
+ "description": "Export the specified screen.",
+ "operationId": "exportDecisionTable",
+ "parameters": [
+ {
+ "name": "decision_table_id",
+ "in": "path",
+ "description": "ID of Decision Table to return",
+ "required": true,
+ "schema": {
+ "type": "string"
+ }
+ }
+ ],
"responses": {
"200": {
- "description": "success"
+ "description": "Successfully exported the decision table",
+ "content": {
+ "application/json": {
+ "schema": {
+ "$ref": "#/components/schemas/DecisionTableExported"
+ }
+ }
+ }
+ }
+ }
+ }
+ },
+ "/decision_tables/import": {
+ "post": {
+ "tags": [
+ "DecisionTables"
+ ],
+ "summary": "Import a new Decision Table",
+ "description": "Import the specified Decision Table.",
+ "operationId": "importDecisionTable",
+ "requestBody": {
+ "required": true,
+ "content": {
+ "multipart/form-data": {
+ "schema": {
+ "properties": {
+ "file": {
+ "description": "file to import",
+ "type": "string",
+ "format": "binary"
+ }
+ },
+ "type": "object"
+ }
+ }
+ }
+ },
+ "responses": {
+ "201": {
+ "description": "success",
+ "content": {
+ "application/json": {
+ "schema": {
+ "properties": {
+ "status": {
+ "type": "object"
+ }
+ },
+ "type": "object"
+ }
+ }
+ }
+ }
+ }
+ }
+ },
+ "/decision_tables/{decision_table_id}/execute": {
+ "post": {
+ "tags": [
+ "DecisionTables"
+ ],
+ "summary": "Execute a Decision Table definition",
+ "description": "Execute a Decision Table definition",
+ "operationId": "previewDecisionTable",
+ "parameters": [
+ {
+ "name": "decision_table_id",
+ "in": "path",
+ "description": "Decision Table unique Identifier",
+ "required": true,
+ "schema": {
+ "type": "string"
+ }
+ }
+ ],
+ "responses": {
+ "200": {
+ "description": "Successfully executed",
+ "content": {
+ "application/json": {
+ "schema": {}
+ }
+ }
}
}
}
@@ -1349,14 +1389,54 @@
}
}
},
- "/version_histories": {
+ "/customize-ui": {
+ "post": {
+ "tags": [
+ "CssSettings"
+ ],
+ "summary": "Create or update a new setting",
+ "description": "Create a new Settings css-override",
+ "operationId": "updateCssSetting",
+ "requestBody": {
+ "required": true,
+ "content": {
+ "application/json": {
+ "schema": {
+ "properties": {
+ "variables": {
+ "type": "string"
+ },
+ "sansSerifFont": {
+ "type": "string"
+ }
+ },
+ "type": "object"
+ }
+ }
+ }
+ },
+ "responses": {
+ "201": {
+ "description": "success",
+ "content": {
+ "application/json": {
+ "schema": {
+ "$ref": "#/components/schemas/settings"
+ }
+ }
+ }
+ }
+ }
+ }
+ },
+ "/environment_variables": {
"get": {
"tags": [
- "Version History"
+ "Environment Variables"
],
- "summary": "Return all version History according to the model",
- "description": "Get the list of records of Version History",
- "operationId": "getVersionHistories",
+ "summary": "Returns all environmentVariables that the user has access to. For security, values are not included.",
+ "description": "Fetch a collection of variables based on paged request and filter if provided",
+ "operationId": "getEnvironmentVariables",
"parameters": [
{
"$ref": "#/components/parameters/filter"
@@ -1376,7 +1456,7 @@
],
"responses": {
"200": {
- "description": "list of Version History",
+ "description": "list of environmentVariables",
"content": {
"application/json": {
"schema": {
@@ -1384,16 +1464,11 @@
"data": {
"type": "array",
"items": {
- "$ref": "#/components/schemas/versionHistory"
+ "$ref": "#/components/schemas/EnvironmentVariable"
}
},
"meta": {
- "type": "object",
- "allOf": [
- {
- "$ref": "#/components/schemas/metadata"
- }
- ]
+ "type": "object"
}
},
"type": "object"
@@ -1405,17 +1480,17 @@
},
"post": {
"tags": [
- "Version History"
+ "Environment Variables"
],
- "summary": "Save a new Version History",
- "description": "Create a new Version History.",
- "operationId": "createVersion",
+ "summary": "Create a new environment variable",
+ "description": "Creates a new global Environment Variable in the system",
+ "operationId": "createEnvironmentVariable",
"requestBody": {
"required": true,
"content": {
"application/json": {
"schema": {
- "$ref": "#/components/schemas/versionHistoryEditable"
+ "$ref": "#/components/schemas/EnvironmentVariableEditable"
}
}
}
@@ -1426,7 +1501,7 @@
"content": {
"application/json": {
"schema": {
- "$ref": "#/components/schemas/versionHistory"
+ "$ref": "#/components/schemas/EnvironmentVariable"
}
}
}
@@ -1434,32 +1509,32 @@
}
}
},
- "/version_histories/{version_history_id}": {
+ "/environment_variables/{environment_variable_id}": {
"get": {
"tags": [
- "Version History"
+ "Environment Variables"
],
- "summary": "Get single Version History by ID",
- "description": "Get a single Version History.",
- "operationId": "getVersionHistoryById",
+ "summary": "Get an environment variable by id. For security, the value is not included.",
+ "description": "Return an environment variable instance\nUsing implicit model binding, will automatically return 404 if variable now found",
+ "operationId": "getEnvironmentVariableById",
"parameters": [
{
- "name": "version_history_id",
+ "name": "environment_variable_id",
"in": "path",
- "description": "ID of Version History to return",
+ "description": "ID of environment_variables to return",
"required": true,
"schema": {
- "type": "string"
+ "type": "integer"
}
}
],
"responses": {
- "200": {
- "description": "Successfully found the Version History",
+ "201": {
+ "description": "success",
"content": {
"application/json": {
"schema": {
- "$ref": "#/components/schemas/versionHistory"
+ "$ref": "#/components/schemas/EnvironmentVariable"
}
}
}
@@ -1468,19 +1543,19 @@
},
"put": {
"tags": [
- "Version History"
+ "Environment Variables"
],
- "summary": "Update a Version History",
- "description": "Update a Version History.",
- "operationId": "updateVersion",
+ "summary": "Update an environment variable",
+ "description": "Update an environment variable",
+ "operationId": "updateEnvironmentVariable",
"parameters": [
{
- "name": "version_history_id",
+ "name": "environment_variable_id",
"in": "path",
- "description": "ID of Version History to return",
+ "description": "ID of environment variables to update",
"required": true,
"schema": {
- "type": "string"
+ "type": "integer"
}
}
],
@@ -1489,18 +1564,18 @@
"content": {
"application/json": {
"schema": {
- "$ref": "#/components/schemas/versionHistoryEditable"
+ "$ref": "#/components/schemas/EnvironmentVariableEditable"
}
}
}
},
"responses": {
- "204": {
+ "200": {
"description": "success",
"content": {
"application/json": {
"schema": {
- "$ref": "#/components/schemas/versionHistory"
+ "$ref": "#/components/schemas/EnvironmentVariable"
}
}
}
@@ -1509,116 +1584,36 @@
},
"delete": {
"tags": [
- "Version History"
+ "Environment Variables"
],
- "summary": "Delete a Version History",
- "description": "Delete a Version History.",
- "operationId": "deleteVersion",
+ "summary": "Delete an environment variable",
+ "operationId": "deleteEnvironmentVariable",
"parameters": [
{
- "name": "version_history_id",
+ "name": "environment_variable_id",
"in": "path",
- "description": "ID of Version History to return",
+ "description": "ID of environment_variables to return",
"required": true,
"schema": {
- "type": "string"
- }
- }
- ],
- "responses": {
- "204": {
- "description": "success",
- "content": {
- "application/json": {
- "schema": {
- "$ref": "#/components/schemas/versionHistory"
- }
- }
- }
- }
- }
- }
- },
- "/version_histories/clone": {
- "post": {
- "tags": [
- "Version History"
- ],
- "summary": "Clone a new Version History",
- "description": "Clone a new Version History.",
- "operationId": "cloneVersion",
- "requestBody": {
- "required": true,
- "content": {
- "application/json": {
- "schema": {
- "$ref": "#/components/schemas/versionHistoryEditable"
- }
- }
- }
- },
- "responses": {
- "201": {
- "description": "success",
- "content": {
- "application/json": {
- "schema": {
- "$ref": "#/components/schemas/versionHistory"
- }
- }
+ "type": "integer"
}
}
- }
- }
- },
- "/customize-ui": {
- "post": {
- "tags": [
- "CssSettings"
],
- "summary": "Create or update a new setting",
- "description": "Create a new Settings css-override",
- "operationId": "updateCssSetting",
- "requestBody": {
- "required": true,
- "content": {
- "application/json": {
- "schema": {
- "properties": {
- "variables": {
- "type": "string"
- },
- "sansSerifFont": {
- "type": "string"
- }
- },
- "type": "object"
- }
- }
- }
- },
"responses": {
- "201": {
- "description": "success",
- "content": {
- "application/json": {
- "schema": {
- "$ref": "#/components/schemas/settings"
- }
- }
- }
+ "200": {
+ "description": "success"
}
}
}
},
- "/environment_variables": {
+ "/files": {
"get": {
"tags": [
- "Environment Variables"
+ "Files"
],
- "summary": "Returns all environmentVariables that the user has access to. For security, values are not included.",
- "description": "Fetch a collection of variables based on paged request and filter if provided",
- "operationId": "getEnvironmentVariables",
+ "summary": "Returns the list of files",
+ "description": "Display a listing of the resource.",
+ "operationId": "getFiles",
"parameters": [
{
"$ref": "#/components/parameters/filter"
@@ -1631,14 +1626,11 @@
},
{
"$ref": "#/components/parameters/per_page"
- },
- {
- "$ref": "#/components/parameters/include"
}
],
"responses": {
"200": {
- "description": "list of environmentVariables",
+ "description": "list of files",
"content": {
"application/json": {
"schema": {
@@ -1646,11 +1638,11 @@
"data": {
"type": "array",
"items": {
- "$ref": "#/components/schemas/EnvironmentVariable"
+ "$ref": "#/components/schemas/media"
}
},
"meta": {
- "type": "object"
+ "$ref": "#/components/schemas/metadata"
}
},
"type": "object"
@@ -1662,28 +1654,87 @@
},
"post": {
"tags": [
- "Environment Variables"
+ "Files"
+ ],
+ "summary": "Save a new media file. Note: To upload files to a request, use createRequestFile in the RequestFile API",
+ "description": "Store a newly created resource in storage.",
+ "operationId": "createFile",
+ "parameters": [
+ {
+ "name": "model_id",
+ "in": "query",
+ "description": "ID of the model to which the file will be associated",
+ "required": true,
+ "schema": {
+ "type": "integer"
+ }
+ },
+ {
+ "name": "model",
+ "in": "query",
+ "description": "Full namespaced class of the model to associate",
+ "required": true,
+ "schema": {
+ "type": "string"
+ }
+ },
+ {
+ "name": "data_name",
+ "in": "query",
+ "description": "Name of the variable used in a request",
+ "required": false,
+ "schema": {
+ "type": "string"
+ }
+ },
+ {
+ "name": "collection",
+ "in": "query",
+ "description": "Media collection name. For requests, use 'default'",
+ "required": false,
+ "schema": {
+ "type": "string"
+ }
+ }
],
- "summary": "Create a new environment variable",
- "description": "Creates a new global Environment Variable in the system",
- "operationId": "createEnvironmentVariable",
"requestBody": {
"required": true,
"content": {
- "application/json": {
+ "multipart/form-data": {
"schema": {
- "$ref": "#/components/schemas/EnvironmentVariableEditable"
+ "properties": {
+ "file": {
+ "description": "save a new media file",
+ "type": "string",
+ "format": "binary"
+ }
+ },
+ "type": "object"
}
}
}
},
"responses": {
- "201": {
+ "200": {
"description": "success",
"content": {
"application/json": {
"schema": {
- "$ref": "#/components/schemas/EnvironmentVariable"
+ "properties": {
+ "id": {
+ "type": "string"
+ },
+ "model_id": {
+ "type": "string"
+ },
+ "file_name": {
+ "type": "string"
+ },
+ "mime_type": {
+ "type": "string"
+ }
+ },
+ "type": "object"
}
}
}
@@ -1691,19 +1742,19 @@
}
}
},
- "/environment_variables/{environment_variable_id}": {
+ "/files/{file_id}": {
"get": {
"tags": [
- "Environment Variables"
+ "Files"
],
- "summary": "Get an environment variable by id. For security, the value is not included.",
- "description": "Return an environment variable instance\nUsing implicit model binding, will automatically return 404 if variable now found",
- "operationId": "getEnvironmentVariableById",
+ "summary": "Get the metadata of a file. To actually fetch the file see Get File Contents",
+ "description": "Get a single media file.",
+ "operationId": "getFileById",
"parameters": [
{
- "name": "environment_variable_id",
+ "name": "file_id",
"in": "path",
- "description": "ID of environment_variables to return",
+ "description": "ID of the file to return",
"required": true,
"schema": {
"type": "integer"
@@ -1711,266 +1762,33 @@
}
],
"responses": {
- "201": {
- "description": "success",
+ "200": {
+ "description": "Successfully found the file",
"content": {
"application/json": {
"schema": {
- "$ref": "#/components/schemas/EnvironmentVariable"
+ "$ref": "#/components/schemas/media"
}
}
}
+ },
+ "404": {
+ "$ref": "#/components/responses/404"
}
}
},
- "put": {
+ "delete": {
"tags": [
- "Environment Variables"
+ "Files"
],
- "summary": "Update an environment variable",
- "description": "Update an environment variable",
- "operationId": "updateEnvironmentVariable",
+ "summary": "Delete a media file",
+ "description": "Remove the specified resource from storage.",
+ "operationId": "deleteFile",
"parameters": [
{
- "name": "environment_variable_id",
+ "name": "file_id",
"in": "path",
- "description": "ID of environment variables to update",
- "required": true,
- "schema": {
- "type": "integer"
- }
- }
- ],
- "requestBody": {
- "required": true,
- "content": {
- "application/json": {
- "schema": {
- "$ref": "#/components/schemas/EnvironmentVariableEditable"
- }
- }
- }
- },
- "responses": {
- "200": {
- "description": "success",
- "content": {
- "application/json": {
- "schema": {
- "$ref": "#/components/schemas/EnvironmentVariable"
- }
- }
- }
- }
- }
- },
- "delete": {
- "tags": [
- "Environment Variables"
- ],
- "summary": "Delete an environment variable",
- "operationId": "deleteEnvironmentVariable",
- "parameters": [
- {
- "name": "environment_variable_id",
- "in": "path",
- "description": "ID of environment_variables to return",
- "required": true,
- "schema": {
- "type": "integer"
- }
- }
- ],
- "responses": {
- "200": {
- "description": "success"
- }
- }
- }
- },
- "/files": {
- "get": {
- "tags": [
- "Files"
- ],
- "summary": "Returns the list of files",
- "description": "Display a listing of the resource.",
- "operationId": "getFiles",
- "parameters": [
- {
- "$ref": "#/components/parameters/filter"
- },
- {
- "$ref": "#/components/parameters/order_by"
- },
- {
- "$ref": "#/components/parameters/order_direction"
- },
- {
- "$ref": "#/components/parameters/per_page"
- }
- ],
- "responses": {
- "200": {
- "description": "list of files",
- "content": {
- "application/json": {
- "schema": {
- "properties": {
- "data": {
- "type": "array",
- "items": {
- "$ref": "#/components/schemas/media"
- }
- },
- "meta": {
- "$ref": "#/components/schemas/metadata"
- }
- },
- "type": "object"
- }
- }
- }
- }
- }
- },
- "post": {
- "tags": [
- "Files"
- ],
- "summary": "Save a new media file. Note: To upload files to a request, use createRequestFile in the RequestFile API",
- "description": "Store a newly created resource in storage.",
- "operationId": "createFile",
- "parameters": [
- {
- "name": "model_id",
- "in": "query",
- "description": "ID of the model to which the file will be associated",
- "required": true,
- "schema": {
- "type": "integer"
- }
- },
- {
- "name": "model",
- "in": "query",
- "description": "Full namespaced class of the model to associate",
- "required": true,
- "schema": {
- "type": "string"
- }
- },
- {
- "name": "data_name",
- "in": "query",
- "description": "Name of the variable used in a request",
- "required": false,
- "schema": {
- "type": "string"
- }
- },
- {
- "name": "collection",
- "in": "query",
- "description": "Media collection name. For requests, use 'default'",
- "required": false,
- "schema": {
- "type": "string"
- }
- }
- ],
- "requestBody": {
- "required": true,
- "content": {
- "multipart/form-data": {
- "schema": {
- "properties": {
- "file": {
- "description": "save a new media file",
- "type": "string",
- "format": "binary"
- }
- },
- "type": "object"
- }
- }
- }
- },
- "responses": {
- "200": {
- "description": "success",
- "content": {
- "application/json": {
- "schema": {
- "properties": {
- "id": {
- "type": "string"
- },
- "model_id": {
- "type": "string"
- },
- "file_name": {
- "type": "string"
- },
- "mime_type": {
- "type": "string"
- }
- },
- "type": "object"
- }
- }
- }
- }
- }
- }
- },
- "/files/{file_id}": {
- "get": {
- "tags": [
- "Files"
- ],
- "summary": "Get the metadata of a file. To actually fetch the file see Get File Contents",
- "description": "Get a single media file.",
- "operationId": "getFileById",
- "parameters": [
- {
- "name": "file_id",
- "in": "path",
- "description": "ID of the file to return",
- "required": true,
- "schema": {
- "type": "integer"
- }
- }
- ],
- "responses": {
- "200": {
- "description": "Successfully found the file",
- "content": {
- "application/json": {
- "schema": {
- "$ref": "#/components/schemas/media"
- }
- }
- }
- },
- "404": {
- "$ref": "#/components/responses/404"
- }
- }
- },
- "delete": {
- "tags": [
- "Files"
- ],
- "summary": "Delete a media file",
- "description": "Remove the specified resource from storage.",
- "operationId": "deleteFile",
- "parameters": [
- {
- "name": "file_id",
- "in": "path",
- "description": "ID of the file",
+ "description": "ID of the file",
"required": true,
"schema": {
"type": "integer"
@@ -2878,7 +2696,7 @@
],
"summary": "Update the permissions of a user",
"description": "Update permissions",
- "operationId": "51b3555fb753f44324bf5c3880e01454",
+ "operationId": "updatePermissions",
"requestBody": {
"required": true,
"content": {
@@ -3131,6 +2949,9 @@
{
"$ref": "#/components/parameters/include"
},
+ {
+ "$ref": "#/components/parameters/pmql"
+ },
{
"name": "simplified_data_for_selector",
"in": "query",
@@ -3228,6 +3049,22 @@
}
}
}
+ },
+ "204": {
+ "description": "Process not found",
+ "content": {
+ "application/json": {
+ "schema": {
+ "properties": {
+ "message": {
+ "type": "string",
+ "example": "The requested process was not found"
+ }
+ },
+ "type": "object"
+ }
+ }
+ }
}
}
},
@@ -3640,7 +3477,7 @@
],
"summary": "Check if the import is ready",
"description": "Check if the import is ready",
- "operationId": "6a131993b7c879ddcd3d3a291dd8380f",
+ "operationId": "importReady",
"parameters": [
{
"name": "code",
@@ -5130,6 +4967,9 @@
"items": {
"type": "object"
}
+ },
+ "sync": {
+ "type": "boolean"
}
},
"type": "object"
@@ -6922,225 +6762,2307 @@
}
}
}
- }
- },
- "components": {
- "schemas": {
- "DateTime": {
- "properties": {
- "date": {
- "type": "string"
- }
- },
- "type": "object"
- },
- "collectionsEditable": {
+ },
+ "/processes/variables": {
+ "get": {
+ "tags": [
+ "Processes Variables"
+ ],
+ "summary": "Get variables for multiple processes with pagination",
+ "operationId": "getProcessesVariables",
+ "parameters": [
+ {
+ "name": "processIds",
+ "in": "query",
+ "description": "Comma-separated list of process IDs",
+ "required": false,
+ "schema": {
+ "type": "string",
+ "example": "1,2,3",
+ "nullable": true
+ }
+ },
+ {
+ "name": "page",
+ "in": "query",
+ "description": "Page number",
+ "required": false,
+ "schema": {
+ "type": "integer",
+ "default": 1
+ }
+ },
+ {
+ "name": "per_page",
+ "in": "query",
+ "description": "Items per page",
+ "required": false,
+ "schema": {
+ "type": "integer",
+ "default": 20
+ }
+ }
+ ],
+ "responses": {
+ "200": {
+ "description": "Successful response",
+ "content": {
+ "application/json": {
+ "schema": {
+ "properties": {
+ "data": {
+ "type": "array",
+ "items": {
+ "$ref": "#/components/schemas/Variable"
+ }
+ },
+ "meta": {
+ "$ref": "#/components/schemas/PaginationMeta"
+ }
+ },
+ "type": "object"
+ }
+ }
+ }
+ }
+ },
+ "servers": [
+ {
+ "url": "https://pm4.local:8092/api/1.1",
+ "description": "API v1.1 Server"
+ }
+ ]
+ }
+ },
+ "/analytics-reporting": {
+ "get": {
+ "tags": [
+ "AnalyticsReporting"
+ ],
+ "summary": "Returns all analytics reporting that the user has access to",
+ "description": "Get a list of Analytics Reporting.",
+ "operationId": "getAnalyticsReporting",
+ "parameters": [
+ {
+ "$ref": "#/components/parameters/filter"
+ },
+ {
+ "$ref": "#/components/parameters/order_by"
+ },
+ {
+ "$ref": "#/components/parameters/order_direction"
+ },
+ {
+ "$ref": "#/components/parameters/per_page"
+ },
+ {
+ "$ref": "#/components/parameters/include"
+ }
+ ],
+ "responses": {
+ "200": {
+ "description": "list of analytics reporting",
+ "content": {
+ "application/json": {
+ "schema": {
+ "properties": {
+ "data": {
+ "type": "array",
+ "items": {
+ "$ref": "#/components/schemas/analyticsReporting"
+ }
+ },
+ "meta": {
+ "$ref": "#/components/schemas/metadata"
+ }
+ },
+ "type": "object"
+ }
+ }
+ }
+ }
+ }
+ },
+ "post": {
+ "tags": [
+ "AnalyticsReporting"
+ ],
+ "summary": "Save a new Analytics Reporting",
+ "description": "Create a new Analytics Reporting.",
+ "operationId": "createAnalyticsReporting",
+ "requestBody": {
+ "required": true,
+ "content": {
+ "application/json": {
+ "schema": {
+ "$ref": "#/components/schemas/analyticsReportingEditable"
+ }
+ }
+ }
+ },
+ "responses": {
+ "201": {
+ "description": "success",
+ "content": {
+ "application/json": {
+ "schema": {
+ "$ref": "#/components/schemas/analyticsReporting"
+ }
+ }
+ }
+ }
+ }
+ }
+ },
+ "/analytics-reporting/{analytic_reporting_id}": {
+ "get": {
+ "tags": [
+ "AnalyticsReporting"
+ ],
+ "summary": "Get single analytic reporting by ID",
+ "description": "Get a single Analytic Reporting.",
+ "operationId": "getAnalyticReportingById",
+ "parameters": [
+ {
+ "name": "analytic_reporting_id",
+ "in": "path",
+ "description": "ID of analytic reporting to return",
+ "required": true,
+ "schema": {
+ "type": "string"
+ }
+ }
+ ],
+ "responses": {
+ "200": {
+ "description": "Successfully found the analytics reporting",
+ "content": {
+ "application/json": {
+ "schema": {
+ "$ref": "#/components/schemas/analyticsReporting"
+ }
+ }
+ }
+ }
+ }
+ },
+ "put": {
+ "tags": [
+ "AnalyticsReporting"
+ ],
+ "summary": "Update a analytic reporting",
+ "description": "Update a Analytics Reporting.",
+ "operationId": "updateAnalyticReporting",
+ "parameters": [
+ {
+ "name": "analytic_reporting_id",
+ "in": "path",
+ "description": "ID of analytic reporting to update",
+ "required": true,
+ "schema": {
+ "type": "string"
+ }
+ }
+ ],
+ "requestBody": {
+ "required": true,
+ "content": {
+ "application/json": {
+ "schema": {
+ "$ref": "#/components/schemas/analyticsReportingEditable"
+ }
+ }
+ }
+ },
+ "responses": {
+ "204": {
+ "description": "success"
+ }
+ }
+ },
+ "delete": {
+ "tags": [
+ "AnalyticsReporting"
+ ],
+ "summary": "Delete an analytic reporting",
+ "description": "Delete a Analytics Reporting.",
+ "operationId": "deleteAnalyticReporting",
+ "parameters": [
+ {
+ "name": "analytic_reporting_id",
+ "in": "path",
+ "description": "ID of analytic reporting to return",
+ "required": true,
+ "schema": {
+ "type": "string"
+ }
+ }
+ ],
+ "responses": {
+ "204": {
+ "description": "success"
+ }
+ }
+ }
+ },
+ "/collections": {
+ "get": {
+ "tags": [
+ "Collections"
+ ],
+ "summary": "Returns all collections that the user has access to",
+ "description": "Get a list of Collections.",
+ "operationId": "getCollections",
+ "parameters": [
+ {
+ "$ref": "#/components/parameters/filter"
+ },
+ {
+ "$ref": "#/components/parameters/order_by"
+ },
+ {
+ "$ref": "#/components/parameters/order_direction"
+ },
+ {
+ "$ref": "#/components/parameters/per_page"
+ },
+ {
+ "$ref": "#/components/parameters/include"
+ }
+ ],
+ "responses": {
+ "200": {
+ "description": "list of collections",
+ "content": {
+ "application/json": {
+ "schema": {
+ "properties": {
+ "data": {
+ "type": "array",
+ "items": {
+ "$ref": "#/components/schemas/collections"
+ }
+ },
+ "meta": {
+ "$ref": "#/components/schemas/metadata"
+ }
+ },
+ "type": "object"
+ }
+ }
+ }
+ }
+ }
+ },
+ "post": {
+ "tags": [
+ "Collections"
+ ],
+ "summary": "Save a new collections",
+ "description": "Create a new Collection.",
+ "operationId": "createCollection",
+ "requestBody": {
+ "required": true,
+ "content": {
+ "application/json": {
+ "schema": {
+ "$ref": "#/components/schemas/collectionsEditable"
+ }
+ }
+ }
+ },
+ "responses": {
+ "201": {
+ "description": "success",
+ "content": {
+ "application/json": {
+ "schema": {
+ "$ref": "#/components/schemas/collections"
+ }
+ }
+ }
+ }
+ }
+ }
+ },
+ "/collections/{collection_id}": {
+ "get": {
+ "tags": [
+ "Collections"
+ ],
+ "summary": "Get single collections by ID",
+ "description": "Get a single Collection.",
+ "operationId": "getCollectionById",
+ "parameters": [
+ {
+ "name": "collection_id",
+ "in": "path",
+ "description": "ID of collection to return",
+ "required": true,
+ "schema": {
+ "type": "string"
+ }
+ }
+ ],
+ "responses": {
+ "200": {
+ "description": "Successfully found the collections",
+ "content": {
+ "application/json": {
+ "schema": {
+ "$ref": "#/components/schemas/collections"
+ }
+ }
+ }
+ }
+ }
+ },
+ "put": {
+ "tags": [
+ "Collections"
+ ],
+ "summary": "Update a collection",
+ "description": "Update a Collection.",
+ "operationId": "updateCollection",
+ "parameters": [
+ {
+ "name": "collection_id",
+ "in": "path",
+ "description": "ID of collection to update",
+ "required": true,
+ "schema": {
+ "type": "string"
+ }
+ }
+ ],
+ "requestBody": {
+ "required": true,
+ "content": {
+ "application/json": {
+ "schema": {
+ "$ref": "#/components/schemas/collectionsEditable"
+ }
+ }
+ }
+ },
+ "responses": {
+ "204": {
+ "description": "success"
+ }
+ }
+ },
+ "delete": {
+ "tags": [
+ "Collections"
+ ],
+ "summary": "Delete a collection",
+ "description": "Delete a Collection.",
+ "operationId": "deleteCollection",
+ "parameters": [
+ {
+ "name": "collection_id",
+ "in": "path",
+ "description": "ID of collection to return",
+ "required": true,
+ "schema": {
+ "type": "string"
+ }
+ }
+ ],
+ "responses": {
+ "204": {
+ "description": "success"
+ }
+ }
+ }
+ },
+ "/collections/{collection_id}/export": {
+ "post": {
+ "tags": [
+ "Screens"
+ ],
+ "summary": "Trigger export collections job",
+ "description": "Export the specified collection.",
+ "operationId": "exportCollection",
+ "parameters": [
+ {
+ "name": "collection_id",
+ "in": "path",
+ "description": "ID of the collection to export",
+ "required": true,
+ "schema": {
+ "type": "string"
+ }
+ }
+ ],
+ "responses": {
+ "202": {
+ "description": "success"
+ }
+ }
+ }
+ },
+ "/collections/import": {
+ "post": {
+ "tags": [
+ "Collections"
+ ],
+ "summary": "Import a new collection",
+ "description": "Import the specified collection.",
+ "operationId": "importCollection",
+ "requestBody": {
+ "required": true,
+ "content": {
+ "multipart/form-data": {
+ "schema": {
+ "required": [
+ "file"
+ ],
+ "properties": {
+ "file": {
+ "description": "file to upload",
+ "type": "file",
+ "format": "file"
+ }
+ },
+ "type": "object"
+ }
+ }
+ }
+ },
+ "responses": {
+ "201": {
+ "description": "success",
+ "content": {
+ "application/json": {
+ "schema": {
+ "$ref": "#/components/schemas/collections"
+ }
+ }
+ }
+ },
+ "200": {
+ "description": "success"
+ }
+ }
+ }
+ },
+ "/collections/{collection_id}/truncate": {
+ "delete": {
+ "tags": [
+ "Collections"
+ ],
+ "summary": "Deletes all records in a collection",
+ "description": "Truncate a Collection.",
+ "operationId": "truncateCollection",
+ "parameters": [
+ {
+ "name": "collection_id",
+ "in": "path",
+ "description": "ID of collection to truncate",
+ "required": true,
+ "schema": {
+ "type": "string"
+ }
+ }
+ ],
+ "responses": {
+ "204": {
+ "description": "success"
+ }
+ }
+ }
+ },
+ "/collections/{collection_id}/records": {
+ "get": {
+ "tags": [
+ "Collections"
+ ],
+ "summary": "Returns all records",
+ "description": "Get the list of records of a collection.",
+ "operationId": "getRecords",
+ "parameters": [
+ {
+ "name": "collection_id",
+ "in": "path",
+ "description": "ID of collection to get records for",
+ "required": true,
+ "schema": {
+ "type": "string"
+ }
+ },
+ {
+ "name": "pmql",
+ "in": "query",
+ "schema": {
+ "type": "string"
+ }
+ },
+ {
+ "$ref": "#/components/parameters/per_page"
+ },
+ {
+ "$ref": "#/components/parameters/filter"
+ },
+ {
+ "$ref": "#/components/parameters/order_by"
+ },
+ {
+ "$ref": "#/components/parameters/order_direction"
+ },
+ {
+ "$ref": "#/components/parameters/include"
+ }
+ ],
+ "responses": {
+ "200": {
+ "description": "list of records of a collection",
+ "content": {
+ "application/json": {
+ "schema": {
+ "properties": {
+ "data": {
+ "type": "array",
+ "items": {
+ "$ref": "#/components/schemas/records"
+ }
+ },
+ "meta": {
+ "$ref": "#/components/schemas/metadata"
+ }
+ },
+ "type": "object"
+ }
+ }
+ }
+ }
+ }
+ },
+ "post": {
+ "tags": [
+ "Collections"
+ ],
+ "summary": "Save a new record in a collection",
+ "description": "Create a new record in a Collection.",
+ "operationId": "createRecord",
+ "parameters": [
+ {
+ "name": "collection_id",
+ "in": "path",
+ "description": "ID of the collection",
+ "required": true,
+ "schema": {
+ "type": "string"
+ }
+ }
+ ],
+ "requestBody": {
+ "required": true,
+ "content": {
+ "application/json": {
+ "schema": {
+ "$ref": "#/components/schemas/recordsEditable"
+ }
+ }
+ }
+ },
+ "responses": {
+ "201": {
+ "description": "success",
+ "content": {
+ "application/json": {
+ "schema": {
+ "$ref": "#/components/schemas/records"
+ }
+ }
+ }
+ }
+ }
+ }
+ },
+ "/collections/{collection_id}/records/{record_id}": {
+ "get": {
+ "tags": [
+ "Collections"
+ ],
+ "summary": "Get single record of a collection",
+ "description": "Get a single record of a Collection.",
+ "operationId": "getRecordById",
+ "parameters": [
+ {
+ "name": "collection_id",
+ "in": "path",
+ "description": "ID of the collection",
+ "required": true,
+ "schema": {
+ "type": "string"
+ }
+ },
+ {
+ "name": "record_id",
+ "in": "path",
+ "description": "ID of the record to return",
+ "required": true,
+ "schema": {
+ "type": "string"
+ }
+ }
+ ],
+ "responses": {
+ "200": {
+ "description": "Successfully found the record",
+ "content": {
+ "application/json": {
+ "schema": {
+ "$ref": "#/components/schemas/records"
+ }
+ }
+ }
+ }
+ }
+ },
+ "put": {
+ "tags": [
+ "Collections"
+ ],
+ "summary": "Update a record",
+ "description": "Update a record in a Collection.",
+ "operationId": "updateRecord",
+ "parameters": [
+ {
+ "name": "collection_id",
+ "in": "path",
+ "description": "ID of collection",
+ "required": true,
+ "schema": {
+ "type": "string"
+ }
+ },
+ {
+ "name": "record_id",
+ "in": "path",
+ "description": "ID of the record ",
+ "required": true,
+ "schema": {
+ "type": "string"
+ }
+ }
+ ],
+ "requestBody": {
+ "required": true,
+ "content": {
+ "application/json": {
+ "schema": {
+ "$ref": "#/components/schemas/recordsEditable"
+ }
+ }
+ }
+ },
+ "responses": {
+ "204": {
+ "description": "success"
+ }
+ }
+ },
+ "delete": {
+ "tags": [
+ "Collections"
+ ],
+ "summary": "Delete a collection record",
+ "description": "Delete a record of a Collection.",
+ "operationId": "deleteRecord",
+ "parameters": [
+ {
+ "name": "collection_id",
+ "in": "path",
+ "description": "ID of collection",
+ "required": true,
+ "schema": {
+ "type": "string"
+ }
+ },
+ {
+ "name": "record_id",
+ "in": "path",
+ "description": "ID of record in collection",
+ "required": true,
+ "schema": {
+ "type": "string"
+ }
+ }
+ ],
+ "responses": {
+ "204": {
+ "description": "success"
+ }
+ }
+ },
+ "patch": {
+ "tags": [
+ "Collections"
+ ],
+ "summary": "Partial update of a record",
+ "description": "Implements a partial update of a record in a Collection.",
+ "operationId": "patchRecord",
+ "parameters": [
+ {
+ "name": "collection_id",
+ "in": "path",
+ "description": "ID of collection ",
+ "required": true,
+ "schema": {
+ "type": "string"
+ }
+ },
+ {
+ "name": "record_id",
+ "in": "path",
+ "description": "ID of the record ",
+ "required": true,
+ "schema": {
+ "type": "string"
+ }
+ }
+ ],
+ "requestBody": {
+ "required": true,
+ "content": {
+ "application/json": {
+ "schema": {
+ "$ref": "#/components/schemas/collectionsEditable"
+ }
+ }
+ }
+ },
+ "responses": {
+ "200": {
+ "description": "success"
+ }
+ }
+ }
+ },
+ "/comments/tasks": {
+ "get": {
+ "tags": [
+ "Comments"
+ ],
+ "summary": "Returns all the tasks that are active.",
+ "description": "Display a listing of the resource.",
+ "operationId": "getCommentTasks",
+ "parameters": [
+ {
+ "name": "process_request_id",
+ "in": "query",
+ "description": "Process request id",
+ "required": false,
+ "schema": {
+ "type": "integer"
+ }
+ },
+ {
+ "$ref": "#/components/parameters/filter"
+ },
+ {
+ "$ref": "#/components/parameters/order_by"
+ },
+ {
+ "$ref": "#/components/parameters/order_direction"
+ }
+ ],
+ "responses": {
+ "200": {
+ "description": "list all tasks taht are active",
+ "content": {
+ "application/json": {
+ "schema": {
+ "properties": {
+ "data": {
+ "type": "array",
+ "items": {
+ "$ref": "#/components/schemas/processRequestToken"
+ }
+ },
+ "meta": {
+ "$ref": "#/components/schemas/metadata"
+ }
+ },
+ "type": "object"
+ }
+ }
+ }
+ }
+ }
+ }
+ },
+ "/data_source_categories": {
+ "get": {
+ "tags": [
+ "DataSourcesCategories"
+ ],
+ "summary": "Returns all Data Connectors categories that the user has access to",
+ "description": "Display a listing of the Data Connector Categories.",
+ "operationId": "getDataSourceCategories",
+ "parameters": [
+ {
+ "$ref": "#/components/parameters/filter"
+ },
+ {
+ "$ref": "#/components/parameters/order_by"
+ },
+ {
+ "$ref": "#/components/parameters/order_direction"
+ },
+ {
+ "$ref": "#/components/parameters/per_page"
+ }
+ ],
+ "responses": {
+ "200": {
+ "description": "list of Data Connectors categories",
+ "content": {
+ "application/json": {
+ "schema": {
+ "properties": {
+ "data": {
+ "type": "array",
+ "items": {
+ "$ref": "#/components/schemas/DataSourceCategory"
+ }
+ },
+ "meta": {
+ "type": "object",
+ "allOf": [
+ {
+ "$ref": "#/components/schemas/metadata"
+ }
+ ]
+ }
+ },
+ "type": "object"
+ }
+ }
+ }
+ }
+ }
+ },
+ "post": {
+ "tags": [
+ "DataSourcesCategories"
+ ],
+ "summary": "Save a new Data Connector Category",
+ "description": "Store a newly created Data Connector Category in storage",
+ "operationId": "createDataSourceCategory",
+ "requestBody": {
+ "required": true,
+ "content": {
+ "application/json": {
+ "schema": {
+ "$ref": "#/components/schemas/dataSourceCategoryEditable"
+ }
+ }
+ }
+ },
+ "responses": {
+ "201": {
+ "description": "success",
+ "content": {
+ "application/json": {
+ "schema": {
+ "$ref": "#/components/schemas/DataSourceCategory"
+ }
+ }
+ }
+ }
+ }
+ }
+ },
+ "/data_source_categories/{data_source_category_id}": {
+ "get": {
+ "tags": [
+ "DataSourcesCategories"
+ ],
+ "summary": "Get single Data Connector category by ID",
+ "description": "Display the specified data Source category.",
+ "operationId": "getDatasourceCategoryById",
+ "parameters": [
+ {
+ "name": "data_source_category_id",
+ "in": "path",
+ "description": "ID of Data Connector category to return",
+ "required": true,
+ "schema": {
+ "type": "string"
+ }
+ }
+ ],
+ "responses": {
+ "200": {
+ "description": "Successfully found the Data Connector",
+ "content": {
+ "application/json": {
+ "schema": {
+ "$ref": "#/components/schemas/DataSourceCategory"
+ }
+ }
+ }
+ }
+ }
+ },
+ "put": {
+ "tags": [
+ "DataSourcesCategories"
+ ],
+ "summary": "Update a Data Connector Category",
+ "description": "Updates the current element",
+ "operationId": "updateDatasourceCategory",
+ "parameters": [
+ {
+ "name": "data_source_category_id",
+ "in": "path",
+ "description": "ID of Data Connector category to return",
+ "required": true,
+ "schema": {
+ "type": "string"
+ }
+ }
+ ],
+ "requestBody": {
+ "required": true,
+ "content": {
+ "application/json": {
+ "schema": {
+ "$ref": "#/components/schemas/dataSourceCategoryEditable"
+ }
+ }
+ }
+ },
+ "responses": {
+ "200": {
+ "description": "success",
+ "content": {
+ "application/json": {
+ "schema": {
+ "$ref": "#/components/schemas/DataSourceCategory"
+ }
+ }
+ }
+ }
+ }
+ },
+ "delete": {
+ "tags": [
+ "DataSourcesCategories"
+ ],
+ "summary": "Delete a Data Connector category",
+ "description": "Remove the specified resource from storage.",
+ "operationId": "deleteDataSourceCategory",
+ "parameters": [
+ {
+ "name": "data_source_category_id",
+ "in": "path",
+ "description": "ID of Data Connector category to return",
+ "required": true,
+ "schema": {
+ "type": "string"
+ }
+ }
+ ],
+ "responses": {
+ "204": {
+ "description": "success"
+ }
+ }
+ }
+ },
+ "/data_sources": {
+ "get": {
+ "tags": [
+ "DataSources"
+ ],
+ "summary": "Returns all Data Connectors that the user has access to",
+ "description": "Get the list of records of a Data Connector",
+ "operationId": "getDataSources",
+ "parameters": [
+ {
+ "$ref": "#/components/parameters/filter"
+ },
+ {
+ "$ref": "#/components/parameters/order_by"
+ },
+ {
+ "$ref": "#/components/parameters/order_direction"
+ },
+ {
+ "$ref": "#/components/parameters/per_page"
+ },
+ {
+ "$ref": "#/components/parameters/include"
+ }
+ ],
+ "responses": {
+ "200": {
+ "description": "list of Data Connectors",
+ "content": {
+ "application/json": {
+ "schema": {
+ "properties": {
+ "data": {
+ "type": "array",
+ "items": {
+ "$ref": "#/components/schemas/dataSource"
+ }
+ },
+ "meta": {
+ "type": "object",
+ "allOf": [
+ {
+ "$ref": "#/components/schemas/metadata"
+ }
+ ]
+ }
+ },
+ "type": "object"
+ }
+ }
+ }
+ }
+ }
+ },
+ "post": {
+ "tags": [
+ "DataSources"
+ ],
+ "summary": "Save a new Data Connector",
+ "description": "Create a new Data Connector.",
+ "operationId": "createDataSource",
+ "requestBody": {
+ "required": true,
+ "content": {
+ "application/json": {
+ "schema": {
+ "$ref": "#/components/schemas/dataSourceEditable"
+ }
+ }
+ }
+ },
+ "responses": {
+ "201": {
+ "description": "success",
+ "content": {
+ "application/json": {
+ "schema": {
+ "$ref": "#/components/schemas/dataSource"
+ }
+ }
+ }
+ }
+ }
+ }
+ },
+ "/data_sources/{data_source_id}": {
+ "get": {
+ "tags": [
+ "DataSources"
+ ],
+ "summary": "Get single Data Connector by ID",
+ "description": "Get a single Data Connector.",
+ "operationId": "getDataSourceById",
+ "parameters": [
+ {
+ "name": "data_source_id",
+ "in": "path",
+ "description": "ID of Data Connector to return",
+ "required": true,
+ "schema": {
+ "type": "string"
+ }
+ }
+ ],
+ "responses": {
+ "200": {
+ "description": "Successfully found the Data Connector",
+ "content": {
+ "application/json": {
+ "schema": {
+ "$ref": "#/components/schemas/dataSource"
+ }
+ }
+ }
+ }
+ }
+ },
+ "put": {
+ "tags": [
+ "DataSources"
+ ],
+ "summary": "Update a Data Connector",
+ "description": "Update a Data Connector.",
+ "operationId": "updateDataSource",
+ "parameters": [
+ {
+ "name": "data_source_id",
+ "in": "path",
+ "description": "ID of Data Connector to return",
+ "required": true,
+ "schema": {
+ "type": "string"
+ }
+ }
+ ],
+ "requestBody": {
+ "required": true,
+ "content": {
+ "application/json": {
+ "schema": {
+ "$ref": "#/components/schemas/dataSourceEditable"
+ }
+ }
+ }
+ },
+ "responses": {
+ "204": {
+ "description": "success",
+ "content": {
+ "application/json": {
+ "schema": {
+ "$ref": "#/components/schemas/dataSource"
+ }
+ }
+ }
+ }
+ }
+ },
+ "delete": {
+ "tags": [
+ "DataSources"
+ ],
+ "summary": "Delete a Data Connector",
+ "description": "Delete a Data Connector.",
+ "operationId": "deleteDataSource",
+ "parameters": [
+ {
+ "name": "data_source_id",
+ "in": "path",
+ "description": "ID of Data Connector to return",
+ "required": true,
+ "schema": {
+ "type": "string"
+ }
+ }
+ ],
+ "responses": {
+ "204": {
+ "description": "success",
+ "content": {
+ "application/json": {
+ "schema": {
+ "$ref": "#/components/schemas/dataSource"
+ }
+ }
+ }
+ }
+ }
+ }
+ },
+ "/data_sources/{data_source_id}/test": {
+ "post": {
+ "tags": [
+ "DataSources"
+ ],
+ "summary": "Send a Data Connector request",
+ "description": "Send a Data Connector request.",
+ "operationId": "sendDataSource",
+ "parameters": [
+ {
+ "name": "data_source_id",
+ "in": "path",
+ "description": "ID of Data Connector to return",
+ "required": true,
+ "schema": {
+ "type": "string"
+ }
+ }
+ ],
+ "requestBody": {
+ "required": true,
+ "content": {
+ "application/json": {
+ "schema": {
+ "$ref": "#/components/schemas/dataSourceEditable"
+ }
+ }
+ }
+ },
+ "responses": {
+ "204": {
+ "description": "success",
+ "content": {
+ "application/json": {
+ "schema": {
+ "$ref": "#/components/schemas/dataSource"
+ }
+ }
+ }
+ }
+ }
+ }
+ },
+ "/requests/{request_id}/data_sources/{data_source_id}": {
+ "post": {
+ "tags": [
+ "DataSources"
+ ],
+ "summary": "execute Data Source",
+ "description": "Execute a data Source endpoint",
+ "operationId": "executeDataSourceForRequest",
+ "parameters": [
+ {
+ "name": "request_id",
+ "in": "path",
+ "description": "ID of the request in whose context the datasource will be executed",
+ "required": true,
+ "schema": {
+ "type": "string"
+ }
+ },
+ {
+ "name": "data_source_id",
+ "in": "path",
+ "description": "ID of DataSource to be run",
+ "required": true,
+ "schema": {
+ "type": "string"
+ }
+ }
+ ],
+ "requestBody": {
+ "required": true,
+ "content": {
+ "application/json": {
+ "schema": {
+ "properties": {
+ "config": {
+ "$ref": "#/components/schemas/DataSourceCallParameters"
+ }
+ },
+ "type": "object"
+ }
+ }
+ }
+ },
+ "responses": {
+ "200": {
+ "description": "success",
+ "content": {
+ "application/json": {
+ "schema": {
+ "$ref": "#/components/schemas/DataSourceResponse"
+ }
+ }
+ }
+ }
+ }
+ }
+ },
+ "/requests/data_sources/{data_source_id}": {
+ "post": {
+ "tags": [
+ "DataSources"
+ ],
+ "summary": "execute Data Source",
+ "operationId": "executeDataSource",
+ "parameters": [
+ {
+ "name": "data_source_id",
+ "in": "path",
+ "description": "ID of DataSource to be run",
+ "required": true,
+ "schema": {
+ "type": "string"
+ }
+ }
+ ],
+ "requestBody": {
+ "required": true,
+ "content": {
+ "application/json": {
+ "schema": {
+ "properties": {
+ "config": {
+ "$ref": "#/components/schemas/DataSourceCallParameters"
+ },
+ "data": {
+ "type": "object"
+ }
+ },
+ "type": "object"
+ }
+ }
+ }
+ },
+ "responses": {
+ "200": {
+ "description": "success",
+ "content": {
+ "application/json": {
+ "schema": {
+ "$ref": "#/components/schemas/DataSourceResponse"
+ }
+ }
+ }
+ }
+ }
+ }
+ },
+ "/requests/data_sources/{data_source_id}/resources/{endpoint}/data": {
+ "post": {
+ "tags": [
+ "DataSources"
+ ],
+ "summary": "Get Data from Data Source",
+ "operationId": "getDataFromDataSource",
+ "parameters": [
+ {
+ "name": "data_source_id",
+ "in": "path",
+ "description": "ID of DataSource to be run",
+ "required": true,
+ "schema": {
+ "type": "string"
+ }
+ },
+ {
+ "name": "endpoint",
+ "in": "path",
+ "description": "Endpoint of the data source",
+ "required": true,
+ "schema": {
+ "type": "string"
+ }
+ }
+ ],
+ "responses": {
+ "200": {
+ "description": "success",
+ "content": {
+ "application/json": {
+ "schema": {
+ "$ref": "#/components/schemas/DataSourceResponse"
+ }
+ }
+ }
+ }
+ }
+ }
+ },
+ "/version_histories": {
+ "get": {
+ "tags": [
+ "Version History"
+ ],
+ "summary": "Return all version History according to the model",
+ "description": "Get the list of records of Version History",
+ "operationId": "getVersionHistories",
+ "parameters": [
+ {
+ "$ref": "#/components/parameters/filter"
+ },
+ {
+ "$ref": "#/components/parameters/order_by"
+ },
+ {
+ "$ref": "#/components/parameters/order_direction"
+ },
+ {
+ "$ref": "#/components/parameters/per_page"
+ },
+ {
+ "$ref": "#/components/parameters/include"
+ }
+ ],
+ "responses": {
+ "200": {
+ "description": "list of Version History",
+ "content": {
+ "application/json": {
+ "schema": {
+ "properties": {
+ "data": {
+ "type": "array",
+ "items": {
+ "$ref": "#/components/schemas/versionHistory"
+ }
+ },
+ "meta": {
+ "type": "object",
+ "allOf": [
+ {
+ "$ref": "#/components/schemas/metadata"
+ }
+ ]
+ }
+ },
+ "type": "object"
+ }
+ }
+ }
+ }
+ }
+ },
+ "post": {
+ "tags": [
+ "Version History"
+ ],
+ "summary": "Save a new Version History",
+ "description": "Create a new Version History.",
+ "operationId": "createVersion",
+ "requestBody": {
+ "required": true,
+ "content": {
+ "application/json": {
+ "schema": {
+ "$ref": "#/components/schemas/versionHistoryEditable"
+ }
+ }
+ }
+ },
+ "responses": {
+ "201": {
+ "description": "success",
+ "content": {
+ "application/json": {
+ "schema": {
+ "$ref": "#/components/schemas/versionHistory"
+ }
+ }
+ }
+ }
+ }
+ }
+ },
+ "/version_histories/{version_history_id}": {
+ "get": {
+ "tags": [
+ "Version History"
+ ],
+ "summary": "Get single Version History by ID",
+ "description": "Get a single Version History.",
+ "operationId": "getVersionHistoryById",
+ "parameters": [
+ {
+ "name": "version_history_id",
+ "in": "path",
+ "description": "ID of Version History to return",
+ "required": true,
+ "schema": {
+ "type": "string"
+ }
+ }
+ ],
+ "responses": {
+ "200": {
+ "description": "Successfully found the Version History",
+ "content": {
+ "application/json": {
+ "schema": {
+ "$ref": "#/components/schemas/versionHistory"
+ }
+ }
+ }
+ }
+ }
+ },
+ "put": {
+ "tags": [
+ "Version History"
+ ],
+ "summary": "Update a Version History",
+ "description": "Update a Version History.",
+ "operationId": "updateVersion",
+ "parameters": [
+ {
+ "name": "version_history_id",
+ "in": "path",
+ "description": "ID of Version History to return",
+ "required": true,
+ "schema": {
+ "type": "string"
+ }
+ }
+ ],
+ "requestBody": {
+ "required": true,
+ "content": {
+ "application/json": {
+ "schema": {
+ "$ref": "#/components/schemas/versionHistoryEditable"
+ }
+ }
+ }
+ },
+ "responses": {
+ "204": {
+ "description": "success",
+ "content": {
+ "application/json": {
+ "schema": {
+ "$ref": "#/components/schemas/versionHistory"
+ }
+ }
+ }
+ }
+ }
+ },
+ "delete": {
+ "tags": [
+ "Version History"
+ ],
+ "summary": "Delete a Version History",
+ "description": "Delete a Version History.",
+ "operationId": "deleteVersion",
+ "parameters": [
+ {
+ "name": "version_history_id",
+ "in": "path",
+ "description": "ID of Version History to return",
+ "required": true,
+ "schema": {
+ "type": "string"
+ }
+ }
+ ],
+ "responses": {
+ "204": {
+ "description": "success",
+ "content": {
+ "application/json": {
+ "schema": {
+ "$ref": "#/components/schemas/versionHistory"
+ }
+ }
+ }
+ }
+ }
+ }
+ },
+ "/version_histories/clone": {
+ "post": {
+ "tags": [
+ "Version History"
+ ],
+ "summary": "Clone a new Version History",
+ "description": "Clone a new Version History.",
+ "operationId": "cloneVersion",
+ "requestBody": {
+ "required": true,
+ "content": {
+ "application/json": {
+ "schema": {
+ "$ref": "#/components/schemas/versionHistoryEditable"
+ }
+ }
+ }
+ },
+ "responses": {
+ "201": {
+ "description": "success",
+ "content": {
+ "application/json": {
+ "schema": {
+ "$ref": "#/components/schemas/versionHistory"
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ },
+ "components": {
+ "schemas": {
+ "DateTime": {
+ "properties": {
+ "date": {
+ "type": "string"
+ }
+ },
+ "type": "object"
+ },
+ "decisionTableEditable": {
+ "properties": {
+ "id": {
+ "description": "Class Screen",
+ "type": "string",
+ "format": "id"
+ },
+ "name": {
+ "type": "string"
+ },
+ "description": {
+ "type": "string"
+ },
+ "definition": {
+ "type": "string"
+ },
+ "decision_table_categories_id": {
+ "type": "string"
+ }
+ },
+ "type": "object"
+ },
+ "decisionTable": {
+ "type": "object",
+ "allOf": [
+ {
+ "$ref": "#/components/schemas/decisionTableEditable"
+ },
+ {
+ "properties": {
+ "created_at": {
+ "type": "string",
+ "format": "date-time"
+ },
+ "updated_at": {
+ "type": "string",
+ "format": "date-time"
+ }
+ },
+ "type": "object"
+ }
+ ]
+ },
+ "DecisionTableExported": {
+ "properties": {
+ "url": {
+ "type": "string"
+ }
+ },
+ "type": "object"
+ },
+ "decisionTableCategoryEditable": {
+ "properties": {
+ "name": {
+ "description": "Represents a business decision Table category definition.",
+ "type": "string"
+ },
+ "status": {
+ "type": "string",
+ "enum": [
+ "ACTIVE",
+ "INACTIVE"
+ ]
+ }
+ },
+ "type": "object"
+ },
+ "DecisionTableCategory": {
+ "type": "object",
+ "allOf": [
+ {
+ "$ref": "#/components/schemas/decisionTableCategoryEditable"
+ },
+ {
+ "properties": {
+ "id": {
+ "type": "string",
+ "format": "id"
+ },
+ "created_at": {
+ "type": "string",
+ "format": "date-time"
+ },
+ "updated_at": {
+ "type": "string",
+ "format": "date-time"
+ }
+ },
+ "type": "object"
+ }
+ ]
+ },
+ "SavedSearchEditable": {
+ "properties": {
+ "meta": {
+ "description": "Represents an Eloquent model of a Saved Search.",
+ "type": "object",
+ "additionalProperties": "true"
+ },
+ "pmql": {
+ "type": "string"
+ },
+ "title": {
+ "type": "string"
+ },
+ "type": {
+ "type": "string",
+ "enum": [
+ "task",
+ "request"
+ ]
+ },
+ "advanced_filter": {
+ "type": "object",
+ "additionalProperties": "true"
+ }
+ },
+ "type": "object"
+ },
+ "SavedSearch": {
+ "allOf": [
+ {
+ "properties": {
+ "id": {
+ "type": "string",
+ "format": "id"
+ },
+ "user_id": {
+ "type": "string",
+ "format": "id"
+ },
+ "created_at": {
+ "type": "string",
+ "format": "date-time"
+ },
+ "updated_at": {
+ "type": "string",
+ "format": "date-time"
+ }
+ },
+ "type": "object"
+ },
+ {
+ "$ref": "#/components/schemas/SavedSearchEditable"
+ }
+ ]
+ },
+ "SavedSearchIcon": {
+ "properties": {
+ "name": {
+ "type": "string"
+ },
+ "value": {
+ "type": "string"
+ }
+ },
+ "type": "object"
+ },
+ "SavedSearchChartEditable": {
+ "properties": {
+ "title": {
+ "description": "Represents an Eloquent model of a Saved Search Chart.",
+ "type": "string"
+ },
+ "type": {
+ "type": "string",
+ "enum": [
+ "bar",
+ "bar-vertical",
+ "line",
+ "pie",
+ "doughnut"
+ ]
+ },
+ "config": {
+ "type": "object",
+ "additionalProperties": "true"
+ },
+ "sort": {
+ "type": "integer"
+ }
+ },
+ "type": "object"
+ },
+ "SavedSearchChart": {
+ "allOf": [
+ {
+ "properties": {
+ "id": {
+ "type": "string",
+ "format": "id"
+ },
+ "saved_search_id": {
+ "type": "string",
+ "format": "id"
+ },
+ "user_id": {
+ "type": "string",
+ "format": "id"
+ },
+ "created_at": {
+ "type": "string",
+ "format": "date-time"
+ },
+ "updated_at": {
+ "type": "string",
+ "format": "date-time"
+ },
+ "deleted_at": {
+ "type": "string",
+ "format": "date-time"
+ }
+ },
+ "type": "object"
+ },
+ {
+ "$ref": "#/components/schemas/SavedSearchChartEditable"
+ }
+ ]
+ },
+ "ReportEditable": {
+ "properties": {
+ "type": {
+ "type": "string",
+ "enum": [
+ "adhoc",
+ "scheduled"
+ ]
+ },
+ "format": {
+ "type": "string",
+ "enum": [
+ "csv",
+ "xlsx"
+ ]
+ },
+ "saved_search_id": {
+ "type": "integer"
+ },
+ "config": {
+ "type": "object",
+ "additionalProperties": "true"
+ },
+ "to": {
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "subject": {
+ "type": "string"
+ },
+ "body": {
+ "type": "string"
+ }
+ },
+ "type": "object"
+ },
+ "Report": {
+ "allOf": [
+ {
+ "properties": {
+ "id": {
+ "type": "string",
+ "format": "id"
+ },
+ "user_id": {
+ "type": "string",
+ "format": "id"
+ },
+ "created_at": {
+ "type": "string",
+ "format": "date-time"
+ },
+ "updated_at": {
+ "type": "string",
+ "format": "date-time"
+ }
+ },
+ "type": "object"
+ },
+ {
+ "$ref": "#/components/schemas/SavedSearchEditable"
+ }
+ ]
+ },
+ "updateUserGroups": {
"properties": {
- "name": {
+ "groups": {
+ "type": "array",
+ "items": {
+ "type": "integer",
+ "example": 1
+ }
+ }
+ },
+ "type": "object"
+ },
+ "restoreUser": {
+ "properties": {
+ "username": {
+ "description": "Username to restore",
"type": "string"
+ }
+ },
+ "type": "object"
+ },
+ "Variable": {
+ "properties": {
+ "id": {
+ "type": "integer",
+ "example": 1
},
- "description": {
- "type": "string"
+ "process_id": {
+ "type": "integer",
+ "example": 1
},
- "custom_title": {
- "type": "string"
+ "uuid": {
+ "type": "string",
+ "format": "uuid",
+ "example": "550e8400-e29b-41d4-a716-446655440000"
},
- "create_screen_id": {
+ "field": {
"type": "string",
- "format": "id"
+ "enum": [
+ "string",
+ "number",
+ "boolean",
+ "array"
+ ],
+ "example": "string"
},
- "read_screen_id": {
+ "label": {
"type": "string",
- "format": "id"
+ "example": "Variable 1 for Process 1"
},
- "update_screen_id": {
+ "name": {
"type": "string",
- "format": "id"
+ "example": "var_1_1"
},
- "signal_create": {
- "type": "boolean"
+ "asset": {
+ "properties": {
+ "id": {
+ "type": "string",
+ "example": "asset_1_1"
+ },
+ "type": {
+ "type": "string",
+ "enum": [
+ "sensor",
+ "actuator",
+ "controller",
+ "device"
+ ],
+ "example": "sensor"
+ },
+ "name": {
+ "type": "string",
+ "example": "Asset 1 for Process 1"
+ },
+ "uuid": {
+ "type": "string",
+ "format": "uuid",
+ "example": "550e8400-e29b-41d4-a716-446655440000"
+ }
+ },
+ "type": "object"
},
- "signal_update": {
- "type": "boolean"
+ "created_at": {
+ "type": "string",
+ "format": "date-time"
},
- "signal_delete": {
- "type": "boolean"
+ "updated_at": {
+ "type": "string",
+ "format": "date-time"
}
},
"type": "object"
},
- "collections": {
- "allOf": [
- {
- "$ref": "#/components/schemas/collectionsEditable"
+ "PaginationMeta": {
+ "properties": {
+ "current_page": {
+ "type": "integer",
+ "example": 1
},
- {
+ "from": {
+ "type": "integer",
+ "example": 1
+ },
+ "last_page": {
+ "type": "integer",
+ "example": 5
+ },
+ "path": {
+ "type": "string",
+ "example": "http://processmaker.com/processes/variables"
+ },
+ "per_page": {
+ "type": "integer",
+ "example": 20
+ },
+ "to": {
+ "type": "integer",
+ "example": 20
+ },
+ "total": {
+ "type": "integer",
+ "example": 100
+ },
+ "links": {
"properties": {
- "id": {
- "type": "integer"
- },
- "created_at": {
+ "first": {
"type": "string",
- "format": "date-time"
+ "example": "http://processmaker.com/processes/variables?page=1"
},
- "updated_at": {
+ "last": {
"type": "string",
- "format": "date-time"
+ "example": "http://processmaker.com/processes/variables?page=5"
},
- "created_by_id": {
+ "prev": {
"type": "string",
- "format": "id"
+ "nullable": true
},
- "updated_by_id": {
+ "next": {
"type": "string",
- "format": "id"
- },
- "columns": {
- "type": "array",
- "items": {
- "type": "object"
- }
+ "example": "http://processmaker.com/processes/variables?page=2"
}
},
"type": "object"
}
- ]
+ },
+ "type": "object"
},
- "recordsEditable": {
+ "metadata": {
"properties": {
- "data": {
- "type": "object"
+ "filter": {
+ "type": "string"
+ },
+ "sort_by": {
+ "type": "string"
+ },
+ "sort_order": {
+ "type": "string",
+ "enum": [
+ "asc",
+ "desc"
+ ]
+ },
+ "count": {
+ "type": "integer"
+ },
+ "total_pages": {
+ "type": "integer"
+ },
+ "current_page": {
+ "type": "integer"
+ },
+ "form": {
+ "type": "integer"
+ },
+ "last_page": {
+ "type": "integer"
+ },
+ "path": {
+ "type": "string"
+ },
+ "per_page": {
+ "type": "integer"
+ },
+ "to": {
+ "type": "integer"
+ },
+ "total": {
+ "type": "integer"
}
},
"type": "object"
},
- "records": {
+ "taskMetadata": {
+ "type": "object",
"allOf": [
{
- "$ref": "#/components/schemas/recordsEditable"
+ "$ref": "#/components/schemas/metadata"
},
{
"properties": {
- "id": {
- "type": "integer"
+ "filter": {
+ "type": "string"
},
- "collection_id": {
+ "sort_by": {
+ "type": "string"
+ },
+ "sort_order": {
"type": "string",
- "format": "id"
+ "enum": [
+ "asc",
+ "desc"
+ ]
+ },
+ "count": {
+ "type": "integer"
+ },
+ "total_pages": {
+ "type": "integer"
+ },
+ "current_page": {
+ "type": "integer"
+ },
+ "form": {
+ "type": "integer"
+ },
+ "last_page": {
+ "type": "integer"
+ },
+ "path": {
+ "type": "string"
+ },
+ "per_page": {
+ "type": "integer"
+ },
+ "to": {
+ "type": "integer"
+ },
+ "total": {
+ "type": "integer"
+ },
+ "in_overdue": {
+ "type": "integer"
}
},
"type": "object"
}
]
},
- "SavedSearchEditable": {
+ "signalsEditable": {
"properties": {
- "meta": {
- "description": "Represents an Eloquent model of a Saved Search.",
- "type": "object",
- "additionalProperties": "true"
+ "id": {
+ "description": "Represents a business signal definition.",
+ "type": "string",
+ "format": "id"
},
- "pmql": {
+ "name": {
"type": "string"
},
- "title": {
+ "detail": {
"type": "string"
- },
- "type": {
- "type": "string",
- "enum": [
- "task",
- "request"
- ]
- },
- "advanced_filter": {
- "type": "object",
- "additionalProperties": "true"
}
},
"type": "object"
},
- "SavedSearch": {
+ "signals": {
"allOf": [
+ {
+ "$ref": "#/components/schemas/signalsEditable"
+ },
{
"properties": {
- "id": {
- "type": "string",
- "format": "id"
- },
- "user_id": {
- "type": "string",
- "format": "id"
- },
- "created_at": {
- "type": "string",
- "format": "date-time"
+ "type": {
+ "type": "string"
},
- "updated_at": {
- "type": "string",
- "format": "date-time"
+ "processes": {
+ "type": "array",
+ "items": {
+ "properties": {
+ "id": {
+ "type": "integer",
+ "format": "id"
+ },
+ "is_system": {
+ "type": "boolean"
+ },
+ "name": {
+ "type": "string"
+ },
+ "catches": {
+ "type": "array",
+ "items": {
+ "properties": {
+ "id": {
+ "type": "integer",
+ "format": "id"
+ },
+ "name": {
+ "type": "string"
+ },
+ "type": {
+ "type": "string"
+ }
+ },
+ "type": "object"
+ }
+ }
+ },
+ "type": "object"
+ }
}
},
"type": "object"
- },
- {
- "$ref": "#/components/schemas/SavedSearchEditable"
}
]
},
- "SavedSearchIcon": {
+ "columns": {
"properties": {
- "name": {
+ "label": {
"type": "string"
},
- "value": {
+ "field": {
+ "type": "string"
+ },
+ "sortable": {
+ "type": "boolean"
+ },
+ "default": {
+ "type": "boolean"
+ },
+ "format": {
+ "type": "string"
+ },
+ "mask": {
"type": "string"
}
},
"type": "object"
},
- "SavedSearchChartEditable": {
+ "commentsEditable": {
"properties": {
- "title": {
- "description": "Represents an Eloquent model of a Saved Search Chart.",
+ "id": {
+ "description": "Represents a business process definition.",
+ "type": "string",
+ "format": "id"
+ },
+ "user_id": {
+ "type": "string",
+ "format": "id"
+ },
+ "commentable_id": {
+ "type": "string",
+ "format": "id"
+ },
+ "commentable_type": {
+ "type": "string"
+ },
+ "up": {
+ "type": "integer"
+ },
+ "down": {
+ "type": "integer"
+ },
+ "subject": {
+ "type": "string"
+ },
+ "body": {
"type": "string"
},
+ "hidden": {
+ "type": "boolean"
+ },
"type": {
"type": "string",
"enum": [
- "bar",
- "bar-vertical",
- "line",
- "pie",
- "doughnut"
+ "LOG",
+ "MESSAGE"
]
- },
- "config": {
- "type": "object",
- "additionalProperties": "true"
- },
- "sort": {
- "type": "integer"
}
},
"type": "object"
},
- "SavedSearchChart": {
+ "comments": {
+ "type": "object",
"allOf": [
+ {
+ "$ref": "#/components/schemas/commentsEditable"
+ },
{
"properties": {
- "id": {
- "type": "string",
- "format": "id"
- },
- "saved_search_id": {
- "type": "string",
- "format": "id"
- },
- "user_id": {
- "type": "string",
- "format": "id"
- },
"created_at": {
"type": "string",
"format": "date-time"
@@ -7148,67 +9070,35 @@
"updated_at": {
"type": "string",
"format": "date-time"
- },
- "deleted_at": {
- "type": "string",
- "format": "date-time"
}
},
"type": "object"
- },
- {
- "$ref": "#/components/schemas/SavedSearchChartEditable"
}
]
},
- "ReportEditable": {
+ "EnvironmentVariableEditable": {
"properties": {
- "type": {
- "type": "string",
- "enum": [
- "adhoc",
- "scheduled"
- ]
- },
- "format": {
- "type": "string",
- "enum": [
- "csv",
- "xlsx"
- ]
- },
- "saved_search_id": {
- "type": "integer"
- },
- "config": {
- "type": "object",
- "additionalProperties": "true"
- },
- "to": {
- "type": "array",
- "items": {
- "type": "string"
- }
+ "name": {
+ "type": "string"
},
- "subject": {
+ "description": {
"type": "string"
},
- "body": {
+ "value": {
"type": "string"
}
},
"type": "object"
},
- "Report": {
+ "EnvironmentVariable": {
"allOf": [
+ {
+ "$ref": "#/components/schemas/EnvironmentVariableEditable"
+ },
{
"properties": {
"id": {
- "type": "string",
- "format": "id"
- },
- "user_id": {
- "type": "string",
+ "type": "integer",
"format": "id"
},
"created_at": {
@@ -7221,30 +9111,22 @@
}
},
"type": "object"
- },
- {
- "$ref": "#/components/schemas/SavedSearchEditable"
}
]
},
- "versionHistoryEditable": {
+ "groupsEditable": {
"properties": {
- "versionable_id": {
- "description": "Class VersionHistoryCollection",
- "type": "integer"
- },
- "versionable_type": {
- "type": "string"
- },
"name": {
- "type": "string"
- },
- "subject": {
+ "description": "Represents a group definition.",
"type": "string"
},
"description": {
"type": "string"
},
+ "manager_id": {
+ "type": "integer",
+ "format": "id"
+ },
"status": {
"type": "string",
"enum": [
@@ -7255,11 +9137,10 @@
},
"type": "object"
},
- "versionHistory": {
- "type": "object",
+ "groups": {
"allOf": [
{
- "$ref": "#/components/schemas/versionHistoryEditable"
+ "$ref": "#/components/schemas/groupsEditable"
},
{
"properties": {
@@ -7270,272 +9151,209 @@
"updated_at": {
"type": "string",
"format": "date-time"
+ },
+ "id": {
+ "type": "string",
+ "format": "id"
}
},
"type": "object"
}
]
},
- "updateUserGroups": {
- "properties": {
- "groups": {
- "type": "array",
- "items": {
- "type": "integer",
- "example": 1
- }
- }
- },
- "type": "object"
- },
- "restoreUser": {
- "properties": {
- "username": {
- "description": "Username to restore",
- "type": "string"
- }
- },
- "type": "object"
- },
- "metadata": {
+ "groupMembersEditable": {
"properties": {
- "filter": {
- "type": "string"
- },
- "sort_by": {
- "type": "string"
- },
- "sort_order": {
+ "group_id": {
+ "description": "Represents a group Members definition.",
"type": "string",
- "enum": [
- "asc",
- "desc"
- ]
- },
- "count": {
- "type": "integer"
- },
- "total_pages": {
- "type": "integer"
- },
- "current_page": {
- "type": "integer"
- },
- "form": {
- "type": "integer"
- },
- "last_page": {
- "type": "integer"
- },
- "path": {
- "type": "string"
+ "format": "id"
},
- "per_page": {
- "type": "integer"
+ "member_id": {
+ "type": "string",
+ "format": "id"
},
- "to": {
- "type": "integer"
+ "member_type": {
+ "type": "string"
},
- "total": {
- "type": "integer"
+ "description": {
+ "type": "string"
}
},
"type": "object"
},
- "taskMetadata": {
- "type": "object",
+ "groupMembers": {
"allOf": [
{
- "$ref": "#/components/schemas/metadata"
+ "$ref": "#/components/schemas/groupMembersEditable"
},
{
"properties": {
- "filter": {
- "type": "string"
+ "id": {
+ "type": "string",
+ "format": "id"
},
- "sort_by": {
- "type": "string"
+ "created_at": {
+ "type": "string",
+ "format": "date-time"
},
- "sort_order": {
+ "updated_at": {
"type": "string",
- "enum": [
- "asc",
- "desc"
- ]
+ "format": "date-time"
+ }
+ },
+ "type": "object"
+ }
+ ]
+ },
+ "createGroupMembers": {
+ "allOf": [
+ {
+ "$ref": "#/components/schemas/groupMembersEditable"
+ },
+ {
+ "properties": {
+ "id": {
+ "type": "string",
+ "format": "id"
},
- "count": {
- "type": "integer"
+ "group": {
+ "type": "object"
},
- "total_pages": {
- "type": "integer"
+ "member": {
+ "type": "object"
},
- "current_page": {
- "type": "integer"
+ "created_at": {
+ "type": "string",
+ "format": "date-time"
},
- "form": {
- "type": "integer"
+ "updated_at": {
+ "type": "string",
+ "format": "date-time"
+ }
+ },
+ "type": "object"
+ }
+ ]
+ },
+ "getGroupMembersById": {
+ "allOf": [
+ {
+ "properties": {
+ "group_id": {
+ "type": "string",
+ "format": "id"
},
- "last_page": {
- "type": "integer"
+ "member_id": {
+ "type": "string",
+ "format": "id"
},
- "path": {
+ "member_type": {
"type": "string"
},
- "per_page": {
- "type": "integer"
- },
- "to": {
- "type": "integer"
+ "id": {
+ "type": "string",
+ "format": "id"
},
- "total": {
- "type": "integer"
+ "created_at": {
+ "type": "string",
+ "format": "date-time"
},
- "in_overdue": {
- "type": "integer"
+ "updated_at": {
+ "type": "string",
+ "format": "date-time"
}
},
"type": "object"
}
]
},
- "signalsEditable": {
- "properties": {
- "id": {
- "description": "Represents a business signal definition.",
- "type": "string",
- "format": "id"
- },
- "name": {
- "type": "string"
- },
- "detail": {
- "type": "string"
- }
- },
- "type": "object"
- },
- "signals": {
+ "availableGroupMembers": {
"allOf": [
- {
- "$ref": "#/components/schemas/signalsEditable"
- },
{
"properties": {
- "type": {
+ "id": {
+ "type": "string",
+ "format": "id"
+ },
+ "description": {
"type": "string"
},
- "processes": {
- "type": "array",
- "items": {
- "properties": {
- "id": {
- "type": "integer",
- "format": "id"
- },
- "is_system": {
- "type": "boolean"
- },
- "name": {
- "type": "string"
- },
- "catches": {
- "type": "array",
- "items": {
- "properties": {
- "id": {
- "type": "integer",
- "format": "id"
- },
- "name": {
- "type": "string"
- },
- "type": {
- "type": "string"
- }
- },
- "type": "object"
- }
- }
- },
- "type": "object"
- }
+ "name": {
+ "type": "string"
+ },
+ "status": {
+ "type": "string",
+ "enum": [
+ "ACTIVE",
+ "INACTIVE"
+ ]
+ },
+ "created_at": {
+ "type": "string",
+ "format": "date-time"
+ },
+ "updated_at": {
+ "type": "string",
+ "format": "date-time"
}
},
"type": "object"
}
]
},
- "columns": {
- "properties": {
- "label": {
- "type": "string"
- },
- "field": {
- "type": "string"
- },
- "sortable": {
- "type": "boolean"
- },
- "default": {
- "type": "boolean"
- },
- "format": {
- "type": "string"
- },
- "mask": {
- "type": "string"
- }
- },
- "type": "object"
- },
- "commentsEditable": {
+ "mediaEditable": {
"properties": {
"id": {
- "description": "Represents a business process definition.",
- "type": "string",
+ "description": "Represents media files stored in the database",
+ "type": "integer",
"format": "id"
},
- "user_id": {
- "type": "string",
+ "model_id": {
+ "type": "integer",
"format": "id"
},
- "commentable_id": {
+ "model_type": {
"type": "string",
"format": "id"
},
- "commentable_type": {
+ "collection_name": {
"type": "string"
},
- "up": {
- "type": "integer"
+ "name": {
+ "type": "string"
},
- "down": {
- "type": "integer"
+ "file_name": {
+ "type": "string"
},
- "subject": {
+ "mime_type": {
"type": "string"
},
- "body": {
+ "disk": {
"type": "string"
},
- "hidden": {
- "type": "boolean"
+ "size": {
+ "type": "integer"
},
- "type": {
- "type": "string",
- "enum": [
- "LOG",
- "MESSAGE"
- ]
+ "manipulations": {
+ "type": "object"
+ },
+ "custom_properties": {
+ "type": "object"
+ },
+ "responsive_images": {
+ "type": "object"
+ },
+ "order_column": {
+ "type": "integer"
}
},
"type": "object"
},
- "comments": {
+ "media": {
"type": "object",
"allOf": [
{
- "$ref": "#/components/schemas/commentsEditable"
+ "$ref": "#/components/schemas/mediaEditable"
},
{
"properties": {
@@ -7552,30 +9370,63 @@
}
]
},
- "EnvironmentVariableEditable": {
+ "mediaExported": {
+ "properties": {
+ "url": {
+ "type": "string"
+ }
+ },
+ "type": "object"
+ },
+ "NotificationEditable": {
"properties": {
+ "type": {
+ "description": "Represents a notification definition.",
+ "type": "string"
+ },
+ "notifiable_type": {
+ "type": "string"
+ },
+ "notifiable_id": {
+ "type": "integer"
+ },
+ "data": {
+ "type": "string"
+ },
"name": {
"type": "string"
},
- "description": {
+ "message": {
"type": "string"
},
- "value": {
+ "processName": {
+ "type": "string"
+ },
+ "userName": {
+ "type": "string"
+ },
+ "request_id": {
+ "type": "string"
+ },
+ "url": {
"type": "string"
}
},
"type": "object"
},
- "EnvironmentVariable": {
+ "Notification": {
"allOf": [
{
- "$ref": "#/components/schemas/EnvironmentVariableEditable"
+ "$ref": "#/components/schemas/NotificationEditable"
},
{
"properties": {
"id": {
- "type": "integer",
- "format": "id"
+ "type": "string"
+ },
+ "read_at": {
+ "type": "string",
+ "format": "date-time"
},
"created_at": {
"type": "string",
@@ -7590,36 +9441,96 @@
}
]
},
- "groupsEditable": {
+ "ProcessEditable": {
"properties": {
+ "process_category_id": {
+ "description": "Represents a business process definition.",
+ "type": "integer",
+ "format": "id"
+ },
"name": {
- "description": "Represents a group definition.",
"type": "string"
},
- "description": {
+ "case_title": {
"type": "string"
},
- "manager_id": {
- "type": "integer",
- "format": "id"
+ "description": {
+ "type": "string"
},
"status": {
"type": "string",
"enum": [
"ACTIVE",
- "INACTIVE"
+ "INACTIVE",
+ "ARCHIVED"
]
+ },
+ "pause_timer_start": {
+ "type": "integer"
+ },
+ "cancel_screen_id": {
+ "type": "integer"
+ },
+ "has_timer_start_events": {
+ "type": "boolean"
+ },
+ "request_detail_screen_id": {
+ "type": "integer",
+ "format": "id"
+ },
+ "is_valid": {
+ "type": "integer"
+ },
+ "package_key": {
+ "type": "string"
+ },
+ "start_events": {
+ "type": "array",
+ "items": {
+ "$ref": "#/components/schemas/ProcessStartEvents"
+ }
+ },
+ "warnings": {
+ "type": "string"
+ },
+ "self_service_tasks": {
+ "type": "object"
+ },
+ "signal_events": {
+ "type": "array",
+ "items": {
+ "type": "object"
+ }
+ },
+ "category": {
+ "type": "object"
+ },
+ "manager_id": {
+ "type": "integer",
+ "format": "id"
}
},
"type": "object"
},
- "groups": {
+ "Process": {
"allOf": [
{
- "$ref": "#/components/schemas/groupsEditable"
+ "$ref": "#/components/schemas/ProcessEditable"
},
{
"properties": {
+ "user_id": {
+ "type": "integer",
+ "format": "id"
+ },
+ "id": {
+ "type": "string",
+ "format": "id"
+ },
+ "deleted_at": {
+ "type": "string",
+ "format": "date-time"
+ },
"created_at": {
"type": "string",
"format": "date-time"
@@ -7628,104 +9539,123 @@
"type": "string",
"format": "date-time"
},
- "id": {
- "type": "string",
- "format": "id"
+ "notifications": {
+ "type": "object"
+ },
+ "task_notifications": {
+ "type": "object"
}
},
"type": "object"
}
]
},
- "groupMembersEditable": {
+ "ProcessStartEvents": {
"properties": {
- "group_id": {
- "description": "Represents a group Members definition.",
- "type": "string",
- "format": "id"
+ "eventDefinitions": {
+ "type": "object"
},
- "member_id": {
- "type": "string",
- "format": "id"
+ "parallelMultiple": {
+ "type": "boolean"
},
- "member_type": {
+ "outgoing": {
+ "type": "object"
+ },
+ "incoming": {
+ "type": "object"
+ },
+ "id": {
"type": "string"
},
- "description": {
+ "name": {
"type": "string"
}
},
"type": "object"
},
- "groupMembers": {
+ "ProcessWithStartEvents": {
"allOf": [
{
- "$ref": "#/components/schemas/groupMembersEditable"
+ "$ref": "#/components/schemas/Process"
},
{
"properties": {
- "id": {
- "type": "string",
- "format": "id"
- },
- "created_at": {
- "type": "string",
- "format": "date-time"
- },
- "updated_at": {
- "type": "string",
- "format": "date-time"
+ "events": {
+ "type": "array",
+ "items": {
+ "$ref": "#/components/schemas/ProcessStartEvents"
+ }
}
},
"type": "object"
}
]
},
- "createGroupMembers": {
+ "ProcessImport": {
"allOf": [
{
- "$ref": "#/components/schemas/groupMembersEditable"
+ "$ref": "#/components/schemas/ProcessEditable"
},
{
"properties": {
- "id": {
- "type": "string",
- "format": "id"
- },
- "group": {
- "type": "object"
- },
- "member": {
- "type": "object"
+ "status": {
+ "type": "array",
+ "items": {
+ "type": "object"
+ }
},
- "created_at": {
- "type": "string",
- "format": "date-time"
+ "assignable": {
+ "type": "array",
+ "items": {
+ "type": "object"
+ }
},
- "updated_at": {
- "type": "string",
- "format": "date-time"
- }
+ "process": {}
},
"type": "object"
}
]
},
- "getGroupMembersById": {
- "allOf": [
- {
- "properties": {
- "group_id": {
- "type": "string",
- "format": "id"
- },
- "member_id": {
- "type": "string",
- "format": "id"
- },
- "member_type": {
- "type": "string"
- },
+ "ProcessAssignments": {
+ "properties": {
+ "assignable": {
+ "type": "array",
+ "items": {
+ "type": "object"
+ }
+ },
+ "cancel_request": {
+ "type": "object"
+ },
+ "edit_data": {
+ "type": "object"
+ }
+ },
+ "type": "object"
+ },
+ "ProcessCategoryEditable": {
+ "properties": {
+ "name": {
+ "description": "Represents a business process category definition.",
+ "type": "string"
+ },
+ "status": {
+ "type": "string",
+ "enum": [
+ "ACTIVE",
+ "INACTIVE"
+ ]
+ }
+ },
+ "type": "object"
+ },
+ "ProcessCategory": {
+ "allOf": [
+ {
+ "$ref": "#/components/schemas/ProcessCategoryEditable"
+ },
+ {
+ "properties": {
"id": {
"type": "string",
"format": "id"
@@ -7743,27 +9673,39 @@
}
]
},
- "availableGroupMembers": {
+ "processPermissionsEditable": {
+ "properties": {
+ "id": {
+ "description": "Represents a Process permission.",
+ "type": "integer",
+ "format": "id"
+ },
+ "process_id": {
+ "type": "integer",
+ "format": "id"
+ },
+ "permission_id": {
+ "type": "integer",
+ "format": "id"
+ },
+ "assignable_id": {
+ "type": "integer",
+ "format": "id"
+ },
+ "assignable_type": {
+ "type": "string"
+ }
+ },
+ "type": "object"
+ },
+ "processPermissions": {
+ "type": "object",
"allOf": [
+ {
+ "$ref": "#/components/schemas/processPermissionsEditable"
+ },
{
"properties": {
- "id": {
- "type": "string",
- "format": "id"
- },
- "description": {
- "type": "string"
- },
- "name": {
- "type": "string"
- },
- "status": {
- "type": "string",
- "enum": [
- "ACTIVE",
- "INACTIVE"
- ]
- },
"created_at": {
"type": "string",
"format": "date-time"
@@ -7777,62 +9719,80 @@
}
]
},
- "mediaEditable": {
+ "processRequestEditable": {
"properties": {
- "id": {
- "description": "Represents media files stored in the database",
- "type": "integer",
- "format": "id"
- },
- "model_id": {
- "type": "integer",
+ "user_id": {
+ "description": "Represents an Eloquent model of a Request which is an instance of a Process.",
+ "type": "string",
"format": "id"
},
- "model_type": {
+ "callable_id": {
"type": "string",
"format": "id"
},
- "collection_name": {
- "type": "string"
+ "data": {
+ "type": "object"
+ },
+ "status": {
+ "type": "string",
+ "enum": [
+ "ACTIVE",
+ "COMPLETED",
+ "ERROR",
+ "CANCELED"
+ ]
},
"name": {
"type": "string"
},
- "file_name": {
+ "case_title": {
"type": "string"
},
- "mime_type": {
+ "case_title_formatted": {
"type": "string"
},
- "disk": {
+ "user_viewed_at": {
"type": "string"
},
- "size": {
+ "case_number": {
"type": "integer"
},
- "manipulations": {
- "type": "object"
- },
- "custom_properties": {
- "type": "object"
+ "process_id": {
+ "type": "integer"
},
- "responsive_images": {
+ "process": {
"type": "object"
- },
- "order_column": {
- "type": "integer"
}
},
"type": "object"
},
- "media": {
- "type": "object",
+ "processRequest": {
"allOf": [
{
- "$ref": "#/components/schemas/mediaEditable"
+ "$ref": "#/components/schemas/processRequestEditable"
},
{
"properties": {
+ "id": {
+ "type": "string",
+ "format": "id"
+ },
+ "process_id": {
+ "type": "string",
+ "format": "id"
+ },
+ "process_collaboration_id": {
+ "type": "string",
+ "format": "id"
+ },
+ "participant_id": {
+ "type": "string",
+ "format": "id"
+ },
+ "process_category_id": {
+ "type": "string",
+ "format": "id"
+ },
"created_at": {
"type": "string",
"format": "date-time"
@@ -7840,69 +9800,151 @@
"updated_at": {
"type": "string",
"format": "date-time"
+ },
+ "user": {},
+ "participants": {
+ "type": "array",
+ "items": {
+ "$ref": "#/components/schemas/users"
+ }
}
},
"type": "object"
}
]
},
- "mediaExported": {
- "properties": {
- "url": {
- "type": "string"
- }
- },
- "type": "object"
- },
- "NotificationEditable": {
+ "processRequestTokenEditable": {
"properties": {
- "type": {
- "description": "Represents a notification definition.",
- "type": "string"
+ "user_id": {
+ "description": "ProcessRequestToken is used to store the state of a token of the\nNayra engine",
+ "type": "string",
+ "format": "id"
},
- "notifiable_type": {
+ "status": {
"type": "string"
},
- "notifiable_id": {
- "type": "integer"
+ "due_at": {
+ "type": "string",
+ "format": "date-time"
},
- "data": {
- "type": "string"
+ "initiated_at": {
+ "type": "string",
+ "format": "date-time"
},
- "name": {
- "type": "string"
+ "riskchanges_at": {
+ "type": "string",
+ "format": "date-time"
},
- "message": {
+ "subprocess_start_event_id": {
"type": "string"
},
- "processName": {
- "type": "string"
+ "data": {
+ "type": "object"
+ }
+ },
+ "type": "object"
+ },
+ "processRequestToken": {
+ "allOf": [
+ {
+ "$ref": "#/components/schemas/processRequestTokenEditable"
},
- "userName": {
- "type": "string"
+ {
+ "properties": {
+ "id": {
+ "type": "string",
+ "format": "id"
+ },
+ "process_id": {
+ "type": "string",
+ "format": "id"
+ },
+ "process_request_id": {
+ "type": "string",
+ "format": "id"
+ },
+ "element_id": {
+ "type": "string",
+ "format": "id"
+ },
+ "element_type": {
+ "type": "string",
+ "format": "id"
+ },
+ "element_index": {
+ "type": "string"
+ },
+ "element_name": {
+ "type": "string"
+ },
+ "created_at": {
+ "type": "string",
+ "format": "date-time"
+ },
+ "updated_at": {
+ "type": "string",
+ "format": "date-time"
+ },
+ "initiated_at": {
+ "type": "string",
+ "format": "date-time"
+ },
+ "advanceStatus": {
+ "type": "string"
+ },
+ "due_notified": {
+ "type": "integer"
+ },
+ "user": {
+ "type": "object"
+ },
+ "process": {
+ "type": "object"
+ },
+ "process_request": {
+ "type": "object"
+ }
+ },
+ "type": "object"
+ }
+ ]
+ },
+ "taskAssignmentsEditable": {
+ "properties": {
+ "process_id": {
+ "description": "Represents a business process task assignment definition.",
+ "type": "integer",
+ "format": "id"
},
- "request_id": {
- "type": "string"
+ "process_task_id": {
+ "type": "string",
+ "format": "id"
+ },
+ "assignment_id": {
+ "type": "integer",
+ "format": "id"
},
- "url": {
- "type": "string"
+ "assignment_type": {
+ "type": "string",
+ "enum": [
+ "ProcessMaker\\Models\\User",
+ "ProcessMaker\\Models\\Group"
+ ]
}
},
"type": "object"
},
- "Notification": {
+ "taskAssignments": {
+ "type": "object",
"allOf": [
{
- "$ref": "#/components/schemas/NotificationEditable"
+ "$ref": "#/components/schemas/taskAssignmentsEditable"
},
{
"properties": {
"id": {
- "type": "string"
- },
- "read_at": {
- "type": "string",
- "format": "date-time"
+ "type": "integer",
+ "format": "id"
},
"created_at": {
"type": "string",
@@ -7917,96 +9959,56 @@
}
]
},
- "ProcessEditable": {
+ "screensEditable": {
"properties": {
- "process_category_id": {
- "description": "Represents a business process definition.",
- "type": "integer",
- "format": "id"
- },
- "name": {
+ "title": {
+ "description": "Class Screen",
"type": "string"
},
- "case_title": {
+ "type": {
"type": "string"
},
"description": {
"type": "string"
},
- "status": {
- "type": "string",
- "enum": [
- "ACTIVE",
- "INACTIVE",
- "ARCHIVED"
- ]
- },
- "pause_timer_start": {
- "type": "integer"
- },
- "cancel_screen_id": {
- "type": "integer"
- },
- "has_timer_start_events": {
- "type": "boolean"
- },
- "request_detail_screen_id": {
- "type": "integer",
- "format": "id"
- },
- "is_valid": {
- "type": "integer"
- },
- "package_key": {
- "type": "string"
- },
- "start_events": {
+ "config": {
"type": "array",
"items": {
- "$ref": "#/components/schemas/ProcessStartEvents"
+ "type": "object"
}
},
- "warnings": {
- "type": "string"
- },
- "self_service_tasks": {
- "type": "object"
+ "computed": {
+ "type": "array",
+ "items": {
+ "type": "object"
+ }
},
- "signal_events": {
+ "watchers": {
"type": "array",
"items": {
"type": "object"
}
},
- "category": {
- "type": "object"
+ "custom_css": {
+ "type": "string"
},
- "manager_id": {
- "type": "integer",
- "format": "id"
+ "screen_category_id": {
+ "type": "string"
}
},
"type": "object"
},
- "Process": {
+ "screens": {
"allOf": [
{
- "$ref": "#/components/schemas/ProcessEditable"
+ "$ref": "#/components/schemas/screensEditable"
},
{
"properties": {
- "user_id": {
- "type": "integer",
- "format": "id"
- },
"id": {
"type": "string",
"format": "id"
},
- "deleted_at": {
- "type": "string",
- "format": "date-time"
- },
"created_at": {
"type": "string",
"format": "date-time"
@@ -8014,105 +10016,24 @@
"updated_at": {
"type": "string",
"format": "date-time"
- },
- "notifications": {
- "type": "object"
- },
- "task_notifications": {
- "type": "object"
}
},
"type": "object"
}
]
},
- "ProcessStartEvents": {
+ "screenExported": {
"properties": {
- "eventDefinitions": {
- "type": "object"
- },
- "parallelMultiple": {
- "type": "boolean"
- },
- "outgoing": {
- "type": "object"
- },
- "incoming": {
- "type": "object"
- },
- "id": {
- "type": "string"
- },
- "name": {
+ "url": {
"type": "string"
}
},
"type": "object"
},
- "ProcessWithStartEvents": {
- "allOf": [
- {
- "$ref": "#/components/schemas/Process"
- },
- {
- "properties": {
- "events": {
- "type": "array",
- "items": {
- "$ref": "#/components/schemas/ProcessStartEvents"
- }
- }
- },
- "type": "object"
- }
- ]
- },
- "ProcessImport": {
- "allOf": [
- {
- "$ref": "#/components/schemas/ProcessEditable"
- },
- {
- "properties": {
- "status": {
- "type": "array",
- "items": {
- "type": "object"
- }
- },
- "assignable": {
- "type": "array",
- "items": {
- "type": "object"
- }
- },
- "process": {}
- },
- "type": "object"
- }
- ]
- },
- "ProcessAssignments": {
- "properties": {
- "assignable": {
- "type": "array",
- "items": {
- "type": "object"
- }
- },
- "cancel_request": {
- "type": "object"
- },
- "edit_data": {
- "type": "object"
- }
- },
- "type": "object"
- },
- "ProcessCategoryEditable": {
+ "ScreenCategoryEditable": {
"properties": {
"name": {
- "description": "Represents a business process category definition.",
+ "description": "Represents a business screen category definition.",
"type": "string"
},
"status": {
@@ -8125,10 +10046,10 @@
},
"type": "object"
},
- "ProcessCategory": {
+ "ScreenCategory": {
"allOf": [
{
- "$ref": "#/components/schemas/ProcessCategoryEditable"
+ "$ref": "#/components/schemas/ScreenCategoryEditable"
},
{
"properties": {
@@ -8149,124 +10070,70 @@
}
]
},
- "processPermissionsEditable": {
+ "ScreenTypeEditable": {
"properties": {
- "id": {
- "description": "Represents a Process permission.",
- "type": "integer",
- "format": "id"
- },
- "process_id": {
- "type": "integer",
- "format": "id"
- },
- "permission_id": {
- "type": "integer",
- "format": "id"
- },
- "assignable_id": {
- "type": "integer",
- "format": "id"
- },
- "assignable_type": {
+ "name": {
+ "description": "Represents a business screen Type definition.",
"type": "string"
}
},
"type": "object"
},
- "processPermissions": {
- "type": "object",
+ "ScreenType": {
"allOf": [
{
- "$ref": "#/components/schemas/processPermissionsEditable"
+ "$ref": "#/components/schemas/ScreenTypeEditable"
},
{
"properties": {
- "created_at": {
- "type": "string",
- "format": "date-time"
- },
- "updated_at": {
- "type": "string",
- "format": "date-time"
- }
- },
- "type": "object"
- }
- ]
- },
- "processRequestEditable": {
- "properties": {
- "user_id": {
- "description": "Represents an Eloquent model of a Request which is an instance of a Process.",
- "type": "string",
- "format": "id"
- },
- "callable_id": {
- "type": "string",
- "format": "id"
- },
- "data": {
- "type": "object"
- },
- "status": {
- "type": "string",
- "enum": [
- "ACTIVE",
- "COMPLETED",
- "ERROR",
- "CANCELED"
- ]
- },
- "name": {
+ "id": {
+ "type": "string",
+ "format": "id"
+ }
+ },
+ "type": "object"
+ }
+ ]
+ },
+ "scriptsEditable": {
+ "properties": {
+ "title": {
+ "description": "Represents an Eloquent model of a Script",
"type": "string"
},
- "case_title": {
+ "description": {
"type": "string"
},
- "case_title_formatted": {
+ "language": {
"type": "string"
},
- "user_viewed_at": {
+ "code": {
"type": "string"
},
- "case_number": {
+ "timeout": {
"type": "integer"
},
- "process_id": {
+ "run_as_user_id": {
"type": "integer"
},
- "process": {
- "type": "object"
+ "key": {
+ "type": "string"
+ },
+ "script_category_id": {
+ "type": "integer"
}
},
"type": "object"
},
- "processRequest": {
+ "scripts": {
"allOf": [
{
- "$ref": "#/components/schemas/processRequestEditable"
+ "$ref": "#/components/schemas/scriptsEditable"
},
{
"properties": {
"id": {
- "type": "string",
- "format": "id"
- },
- "process_id": {
- "type": "string",
- "format": "id"
- },
- "process_collaboration_id": {
- "type": "string",
- "format": "id"
- },
- "participant_id": {
- "type": "string",
- "format": "id"
- },
- "process_category_id": {
- "type": "string",
+ "type": "integer",
"format": "id"
},
"created_at": {
@@ -8276,54 +10143,46 @@
"updated_at": {
"type": "string",
"format": "date-time"
- },
- "user": {},
- "participants": {
- "type": "array",
- "items": {
- "$ref": "#/components/schemas/users"
- }
}
},
"type": "object"
}
]
},
- "processRequestTokenEditable": {
+ "scriptsPreview": {
"properties": {
- "user_id": {
- "description": "ProcessRequestToken is used to store the state of a token of the\nNayra engine",
- "type": "string",
- "format": "id"
- },
"status": {
"type": "string"
},
- "due_at": {
- "type": "string",
- "format": "date-time"
- },
- "initiated_at": {
- "type": "string",
- "format": "date-time"
- },
- "riskchanges_at": {
- "type": "string",
- "format": "date-time"
- },
- "subprocess_start_event_id": {
+ "key": {
"type": "string"
},
- "data": {
+ "output": {
"type": "object"
}
},
"type": "object"
},
- "processRequestToken": {
+ "ScriptCategoryEditable": {
+ "properties": {
+ "name": {
+ "description": "Represents a business script category definition.",
+ "type": "string"
+ },
+ "status": {
+ "type": "string",
+ "enum": [
+ "ACTIVE",
+ "INACTIVE"
+ ]
+ }
+ },
+ "type": "object"
+ },
+ "ScriptCategory": {
"allOf": [
{
- "$ref": "#/components/schemas/processRequestTokenEditable"
+ "$ref": "#/components/schemas/ScriptCategoryEditable"
},
{
"properties": {
@@ -8331,28 +10190,6 @@
"type": "string",
"format": "id"
},
- "process_id": {
- "type": "string",
- "format": "id"
- },
- "process_request_id": {
- "type": "string",
- "format": "id"
- },
- "element_id": {
- "type": "string",
- "format": "id"
- },
- "element_type": {
- "type": "string",
- "format": "id"
- },
- "element_index": {
- "type": "string"
- },
- "element_name": {
- "type": "string"
- },
"created_at": {
"type": "string",
"format": "date-time"
@@ -8360,61 +10197,37 @@
"updated_at": {
"type": "string",
"format": "date-time"
- },
- "initiated_at": {
- "type": "string",
- "format": "date-time"
- },
- "advanceStatus": {
- "type": "string"
- },
- "due_notified": {
- "type": "integer"
- },
- "user": {
- "type": "object"
- },
- "process": {
- "type": "object"
- },
- "process_request": {
- "type": "object"
}
},
"type": "object"
}
]
},
- "taskAssignmentsEditable": {
+ "scriptExecutorsEditable": {
"properties": {
- "process_id": {
- "description": "Represents a business process task assignment definition.",
- "type": "integer",
- "format": "id"
+ "title": {
+ "description": "Represents an Eloquent model of a Script Executor",
+ "type": "string"
},
- "process_task_id": {
- "type": "string",
- "format": "id"
+ "description": {
+ "type": "string"
},
- "assignment_id": {
- "type": "integer",
- "format": "id"
+ "language": {
+ "type": "string"
},
- "assignment_type": {
- "type": "string",
- "enum": [
- "ProcessMaker\\Models\\User",
- "ProcessMaker\\Models\\Group"
- ]
+ "config": {
+ "type": "string"
+ },
+ "is_system": {
+ "type": "boolean"
}
},
"type": "object"
},
- "taskAssignments": {
- "type": "object",
+ "scriptExecutors": {
"allOf": [
{
- "$ref": "#/components/schemas/taskAssignmentsEditable"
+ "$ref": "#/components/schemas/scriptExecutorsEditable"
},
{
"properties": {
@@ -8435,97 +10248,123 @@
}
]
},
- "screensEditable": {
+ "availableLanguages": {
"properties": {
- "title": {
- "description": "Class Screen",
+ "text": {
"type": "string"
},
- "type": {
+ "value": {
"type": "string"
},
- "description": {
+ "initDockerFile": {
+ "type": "string"
+ }
+ },
+ "type": "object"
+ },
+ "securityLog": {
+ "properties": {
+ "id": {
+ "description": "Class SecurityLog",
+ "type": "integer"
+ },
+ "event": {
"type": "string"
},
- "config": {
- "type": "array",
- "items": {
- "type": "object"
- }
+ "ip": {
+ "type": "string"
},
- "computed": {
+ "meta": {
"type": "array",
"items": {
+ "properties": {
+ "os": {
+ "type": "array",
+ "items": {
+ "properties": {
+ "name": {
+ "type": "string"
+ },
+ "version": {
+ "type": "string"
+ }
+ },
+ "type": "object"
+ }
+ },
+ "browser": {
+ "type": "array",
+ "items": {
+ "properties": {
+ "name": {
+ "type": "string"
+ },
+ "version": {
+ "type": "string"
+ }
+ },
+ "type": "object"
+ }
+ },
+ "user_agent": {
+ "type": "string"
+ }
+ },
"type": "object"
}
},
- "watchers": {
+ "user_id": {
+ "type": "integer"
+ },
+ "occured_at": {
+ "type": "string"
+ }
+ },
+ "type": "object"
+ },
+ "settingsEditable": {
+ "properties": {
+ "key": {
+ "description": "Class Settings",
+ "type": "string"
+ },
+ "config": {
"type": "array",
"items": {
"type": "object"
}
},
- "custom_css": {
+ "name": {
"type": "string"
},
- "screen_category_id": {
+ "helper": {
"type": "string"
- }
- },
- "type": "object"
- },
- "screens": {
- "allOf": [
- {
- "$ref": "#/components/schemas/screensEditable"
},
- {
- "properties": {
- "id": {
- "type": "string",
- "format": "id"
- },
- "created_at": {
- "type": "string",
- "format": "date-time"
- },
- "updated_at": {
- "type": "string",
- "format": "date-time"
- }
- },
- "type": "object"
- }
- ]
- },
- "screenExported": {
- "properties": {
- "url": {
+ "group": {
"type": "string"
- }
- },
- "type": "object"
- },
- "ScreenCategoryEditable": {
- "properties": {
- "name": {
- "description": "Represents a business screen category definition.",
+ },
+ "format": {
"type": "string"
},
- "status": {
- "type": "string",
- "enum": [
- "ACTIVE",
- "INACTIVE"
- ]
+ "hidden": {
+ "type": "boolean"
+ },
+ "readonly": {
+ "type": "boolean"
+ },
+ "variables": {
+ "type": "string"
+ },
+ "sansSerifFont": {
+ "type": "string"
}
},
"type": "object"
},
- "ScreenCategory": {
+ "settings": {
"allOf": [
{
- "$ref": "#/components/schemas/ScreenCategoryEditable"
+ "$ref": "#/components/schemas/settingsEditable"
},
{
"properties": {
@@ -8546,71 +10385,166 @@
}
]
},
- "ScreenTypeEditable": {
+ "TokenClient": {
"properties": {
+ "id": {
+ "type": "integer"
+ },
+ "user_id": {
+ "type": "integer"
+ },
"name": {
- "description": "Represents a business screen Type definition.",
"type": "string"
+ },
+ "provider": {
+ "type": "string"
+ },
+ "redirect": {
+ "type": "string"
+ },
+ "personal_access_client": {
+ "type": "boolean"
+ },
+ "password_client": {
+ "type": "boolean"
+ },
+ "revoked": {
+ "type": "boolean"
+ },
+ "created_at": {
+ "type": "string",
+ "format": "date-time"
+ },
+ "updated_at": {
+ "type": "string",
+ "format": "date-time"
}
},
"type": "object"
},
- "ScreenType": {
- "allOf": [
- {
- "$ref": "#/components/schemas/ScreenTypeEditable"
- },
- {
- "properties": {
- "id": {
- "type": "string",
- "format": "id"
- }
- },
- "type": "object"
- }
- ]
- },
- "scriptsEditable": {
+ "usersEditable": {
"properties": {
+ "email": {
+ "description": "The attributes that are mass assignable.",
+ "type": "string",
+ "format": "email"
+ },
+ "firstname": {
+ "type": "string"
+ },
+ "lastname": {
+ "type": "string"
+ },
+ "username": {
+ "type": "string"
+ },
+ "password": {
+ "type": "string"
+ },
+ "address": {
+ "type": "string"
+ },
+ "city": {
+ "type": "string"
+ },
+ "state": {
+ "type": "string"
+ },
+ "postal": {
+ "type": "string"
+ },
+ "country": {
+ "type": "string"
+ },
+ "phone": {
+ "type": "string"
+ },
+ "fax": {
+ "type": "string"
+ },
+ "cell": {
+ "type": "string"
+ },
"title": {
- "description": "Represents an Eloquent model of a Script",
"type": "string"
},
- "description": {
+ "timezone": {
+ "type": "string"
+ },
+ "datetime_format": {
"type": "string"
},
"language": {
"type": "string"
},
- "code": {
+ "is_administrator": {
+ "type": "boolean"
+ },
+ "expires_at": {
"type": "string"
},
- "timeout": {
- "type": "integer"
+ "loggedin_at": {
+ "type": "string"
},
- "run_as_user_id": {
- "type": "integer"
+ "remember_token": {
+ "type": "string"
},
- "key": {
+ "status": {
+ "type": "string",
+ "enum": [
+ "ACTIVE",
+ "INACTIVE",
+ "SCHEDULED",
+ "OUT_OF_OFFICE",
+ "BLOCKED"
+ ]
+ },
+ "fullname": {
"type": "string"
},
- "script_category_id": {
- "type": "integer"
+ "avatar": {
+ "type": "string"
+ },
+ "media": {
+ "type": "array",
+ "items": {
+ "$ref": "#/components/schemas/media"
+ }
+ },
+ "birthdate": {
+ "type": "string",
+ "format": "date"
+ },
+ "delegation_user_id": {
+ "type": "string",
+ "format": "id"
+ },
+ "manager_id": {
+ "type": "string",
+ "format": "id"
+ },
+ "meta": {
+ "type": "object",
+ "additionalProperties": true
+ },
+ "force_change_password": {
+ "type": "boolean"
+ },
+ "email_task_notification": {
+ "type": "boolean"
}
},
"type": "object"
},
- "scripts": {
+ "users": {
"allOf": [
{
- "$ref": "#/components/schemas/scriptsEditable"
+ "$ref": "#/components/schemas/usersEditable"
},
{
"properties": {
"id": {
- "type": "integer",
- "format": "id"
+ "type": "integer"
},
"created_at": {
"type": "string",
@@ -8619,49 +10553,77 @@
"updated_at": {
"type": "string",
"format": "date-time"
+ },
+ "deleted_at": {
+ "type": "string",
+ "format": "date-time"
}
},
"type": "object"
}
]
},
- "scriptsPreview": {
+ "UserToken": {
"properties": {
- "status": {
+ "id": {
+ "type": "string"
+ },
+ "user_id": {
+ "type": "integer"
+ },
+ "client_id": {
+ "type": "integer"
+ },
+ "name": {
"type": "string"
},
- "key": {
- "type": "string"
+ "scopes": {
+ "type": "object"
+ },
+ "revoked": {
+ "type": "boolean"
+ },
+ "client": {
+ "$ref": "#/components/schemas/TokenClient"
+ },
+ "created_at": {
+ "type": "string",
+ "format": "date-time"
+ },
+ "updated_at": {
+ "type": "string",
+ "format": "date-time"
+ },
+ "expires_at": {
+ "type": "string",
+ "format": "date-time"
}
},
"type": "object"
},
- "ScriptCategoryEditable": {
+ "analyticsReportingEditable": {
"properties": {
"name": {
- "description": "Represents a business script category definition.",
"type": "string"
},
- "status": {
- "type": "string",
- "enum": [
- "ACTIVE",
- "INACTIVE"
- ]
+ "description": {
+ "type": "string"
+ },
+ "link": {
+ "type": "string"
}
},
"type": "object"
},
- "ScriptCategory": {
+ "analyticsReporting": {
"allOf": [
{
- "$ref": "#/components/schemas/ScriptCategoryEditable"
+ "$ref": "#/components/schemas/analyticsReportingEditable"
},
{
"properties": {
"id": {
- "type": "string",
- "format": "id"
+ "type": "integer"
},
"created_at": {
"type": "string",
@@ -8670,43 +10632,64 @@
"updated_at": {
"type": "string",
"format": "date-time"
+ },
+ "created_by_id": {
+ "type": "string",
+ "format": "id"
+ },
+ "updated_by_id": {
+ "type": "string",
+ "format": "id"
}
},
"type": "object"
}
]
},
- "scriptExecutorsEditable": {
+ "collectionsEditable": {
"properties": {
- "title": {
- "description": "Represents an Eloquent model of a Script Executor",
+ "name": {
"type": "string"
},
"description": {
"type": "string"
},
- "language": {
+ "custom_title": {
"type": "string"
},
- "config": {
- "type": "string"
+ "create_screen_id": {
+ "type": "string",
+ "format": "id"
},
- "is_system": {
+ "read_screen_id": {
+ "type": "string",
+ "format": "id"
+ },
+ "update_screen_id": {
+ "type": "string",
+ "format": "id"
+ },
+ "signal_create": {
+ "type": "boolean"
+ },
+ "signal_update": {
+ "type": "boolean"
+ },
+ "signal_delete": {
"type": "boolean"
}
},
"type": "object"
},
- "scriptExecutors": {
+ "collections": {
"allOf": [
{
- "$ref": "#/components/schemas/scriptExecutorsEditable"
+ "$ref": "#/components/schemas/collectionsEditable"
},
{
"properties": {
"id": {
- "type": "integer",
- "format": "id"
+ "type": "integer"
},
"created_at": {
"type": "string",
@@ -8715,306 +10698,182 @@
"updated_at": {
"type": "string",
"format": "date-time"
+ },
+ "created_by_id": {
+ "type": "string",
+ "format": "id"
+ },
+ "updated_by_id": {
+ "type": "string",
+ "format": "id"
+ },
+ "columns": {
+ "type": "array",
+ "items": {
+ "type": "object"
+ }
}
},
"type": "object"
}
]
},
- "availableLanguages": {
+ "recordsEditable": {
"properties": {
- "text": {
- "type": "string"
- },
- "value": {
- "type": "string"
- },
- "initDockerFile": {
- "type": "string"
+ "data": {
+ "type": "object"
}
},
"type": "object"
},
- "securityLog": {
- "properties": {
- "id": {
- "description": "Class SecurityLog",
- "type": "integer"
- },
- "event": {
- "type": "string"
+ "records": {
+ "allOf": [
+ {
+ "$ref": "#/components/schemas/recordsEditable"
},
- "ip": {
+ {
+ "properties": {
+ "id": {
+ "type": "integer"
+ },
+ "collection_id": {
+ "type": "string",
+ "format": "id"
+ }
+ },
+ "type": "object"
+ }
+ ]
+ },
+ "DataSourceCallParameters": {
+ "properties": {
+ "endpoint": {
"type": "string"
},
- "meta": {
+ "dataMapping": {
"type": "array",
"items": {
"properties": {
- "os": {
- "type": "array",
- "items": {
- "properties": {
- "name": {
- "type": "string"
- },
- "version": {
- "type": "string"
- }
- },
- "type": "object"
- }
- },
- "browser": {
- "type": "array",
- "items": {
- "properties": {
- "name": {
- "type": "string"
- },
- "version": {
- "type": "string"
- }
- },
- "type": "object"
- }
+ "key": {
+ "type": "string"
},
- "user_agent": {
+ "value": {
"type": "string"
}
},
"type": "object"
}
},
- "user_id": {
- "type": "integer"
- },
- "occured_at": {
- "type": "string"
- }
- },
- "type": "object"
- },
- "settingsEditable": {
- "properties": {
- "key": {
- "description": "Class Settings",
- "type": "string"
- },
- "config": {
+ "outboundConfig": {
"type": "array",
"items": {
+ "properties": {
+ "key": {
+ "type": "string"
+ },
+ "value": {
+ "type": "string"
+ }
+ },
"type": "object"
}
- },
- "name": {
- "type": "string"
- },
- "helper": {
- "type": "string"
- },
- "group": {
- "type": "string"
- },
- "format": {
- "type": "string"
- },
- "hidden": {
- "type": "boolean"
- },
- "readonly": {
- "type": "boolean"
- },
- "variables": {
- "type": "string"
- },
- "sansSerifFont": {
- "type": "string"
}
},
"type": "object"
},
- "settings": {
- "allOf": [
- {
- "$ref": "#/components/schemas/settingsEditable"
- },
- {
- "properties": {
- "id": {
- "type": "string",
- "format": "id"
- },
- "created_at": {
- "type": "string",
- "format": "date-time"
- },
- "updated_at": {
- "type": "string",
- "format": "date-time"
- }
- },
- "type": "object"
- }
- ]
- },
- "TokenClient": {
+ "DataSourceResponse": {
"properties": {
- "id": {
- "type": "integer"
- },
- "user_id": {
+ "status": {
"type": "integer"
},
- "name": {
- "type": "string"
- },
- "provider": {
- "type": "string"
- },
- "redirect": {
- "type": "string"
- },
- "personal_access_client": {
- "type": "boolean"
- },
- "password_client": {
- "type": "boolean"
- },
- "revoked": {
- "type": "boolean"
- },
- "created_at": {
- "type": "string",
- "format": "date-time"
- },
- "updated_at": {
- "type": "string",
- "format": "date-time"
+ "response": {
+ "type": "object"
}
},
"type": "object"
},
- "usersEditable": {
+ "dataSourceEditable": {
"properties": {
- "email": {
- "description": "The attributes that are mass assignable.",
+ "id": {
+ "description": "Class DataSource",
"type": "string",
- "format": "email"
- },
- "firstname": {
- "type": "string"
- },
- "lastname": {
- "type": "string"
- },
- "username": {
- "type": "string"
- },
- "password": {
- "type": "string"
- },
- "address": {
- "type": "string"
- },
- "city": {
- "type": "string"
- },
- "state": {
- "type": "string"
- },
- "postal": {
- "type": "string"
- },
- "country": {
- "type": "string"
- },
- "phone": {
- "type": "string"
+ "format": "id"
},
- "fax": {
+ "name": {
"type": "string"
},
- "cell": {
+ "description": {
"type": "string"
},
- "title": {
+ "endpoints": {
"type": "string"
},
- "timezone": {
+ "mappings": {
"type": "string"
},
- "datetime_format": {
+ "authtype": {
"type": "string"
},
- "language": {
+ "credentials": {
"type": "string"
},
- "is_administrator": {
- "type": "boolean"
- },
- "expires_at": {
+ "status": {
"type": "string"
},
- "loggedin_at": {
+ "data_source_category_id": {
"type": "string"
+ }
+ },
+ "type": "object"
+ },
+ "dataSource": {
+ "type": "object",
+ "allOf": [
+ {
+ "$ref": "#/components/schemas/dataSourceEditable"
},
- "remember_token": {
+ {
+ "properties": {
+ "created_at": {
+ "type": "string",
+ "format": "date-time"
+ },
+ "updated_at": {
+ "type": "string",
+ "format": "date-time"
+ }
+ },
+ "type": "object"
+ }
+ ]
+ },
+ "dataSourceCategoryEditable": {
+ "properties": {
+ "name": {
+ "description": "Represents a business data Source category definition.",
"type": "string"
},
"status": {
"type": "string",
"enum": [
"ACTIVE",
- "INACTIVE",
- "SCHEDULED",
- "OUT_OF_OFFICE",
- "BLOCKED"
+ "INACTIVE"
]
- },
- "fullname": {
- "type": "string"
- },
- "avatar": {
- "type": "string"
- },
- "media": {
- "type": "array",
- "items": {
- "$ref": "#/components/schemas/media"
- }
- },
- "birthdate": {
- "type": "string",
- "format": "date"
- },
- "delegation_user_id": {
- "type": "string",
- "format": "id"
- },
- "manager_id": {
- "type": "string",
- "format": "id"
- },
- "meta": {
- "type": "object",
- "additionalProperties": true
- },
- "force_change_password": {
- "type": "boolean"
}
},
"type": "object"
},
- "users": {
+ "DataSourceCategory": {
+ "type": "object",
"allOf": [
{
- "$ref": "#/components/schemas/usersEditable"
+ "$ref": "#/components/schemas/dataSourceCategoryEditable"
},
{
"properties": {
"id": {
- "type": "integer"
+ "type": "string",
+ "format": "id"
},
"created_at": {
"type": "string",
@@ -9023,53 +10882,60 @@
"updated_at": {
"type": "string",
"format": "date-time"
- },
- "deleted_at": {
- "type": "string",
- "format": "date-time"
}
},
"type": "object"
}
]
},
- "UserToken": {
+ "versionHistoryEditable": {
"properties": {
- "id": {
- "type": "string"
- },
- "user_id": {
+ "versionable_id": {
+ "description": "Class VersionHistoryCollection",
"type": "integer"
},
- "client_id": {
- "type": "integer"
+ "versionable_type": {
+ "type": "string"
},
"name": {
"type": "string"
},
- "scopes": {
- "type": "object"
- },
- "revoked": {
- "type": "boolean"
- },
- "client": {
- "$ref": "#/components/schemas/TokenClient"
- },
- "created_at": {
- "type": "string",
- "format": "date-time"
+ "subject": {
+ "type": "string"
},
- "updated_at": {
- "type": "string",
- "format": "date-time"
+ "description": {
+ "type": "string"
},
- "expires_at": {
+ "status": {
"type": "string",
- "format": "date-time"
+ "enum": [
+ "ACTIVE",
+ "INACTIVE"
+ ]
}
},
"type": "object"
+ },
+ "versionHistory": {
+ "type": "object",
+ "allOf": [
+ {
+ "$ref": "#/components/schemas/versionHistoryEditable"
+ },
+ {
+ "properties": {
+ "created_at": {
+ "type": "string",
+ "format": "date-time"
+ },
+ "updated_at": {
+ "type": "string",
+ "format": "date-time"
+ }
+ },
+ "type": "object"
+ }
+ ]
}
},
"responses": {
@@ -9186,6 +11052,14 @@
"type": "string",
"default": ""
}
+ },
+ "pmql": {
+ "name": "pmql",
+ "in": "query",
+ "description": "PMQL query to filter results",
+ "schema": {
+ "type": "string"
+ }
}
},
"securitySchemes": {
@@ -9194,9 +11068,9 @@
"description": "Laravel passport oauth2 security.",
"flows": {
"authorizationCode": {
- "authorizationUrl": "http://processmaker.test/oauth/authorize",
- "tokenUrl": "http://processmaker.test/oauth/token",
- "refreshUrl": "http://processmaker.test/token/refresh",
+ "authorizationUrl": "https://pm4.local:8092/oauth/authorize",
+ "tokenUrl": "https://pm4.local:8092/oauth/token",
+ "refreshUrl": "https://pm4.local:8092/token/refresh",
"scopes": {}
}
}
@@ -9208,6 +11082,148 @@
}
}
},
+ "tags": [
+ {
+ "name": "DecisionTableCategories",
+ "description": "DecisionTableCategories"
+ },
+ {
+ "name": "DecisionTables",
+ "description": "DecisionTables"
+ },
+ {
+ "name": "SavedSearchCharts",
+ "description": "SavedSearchCharts"
+ },
+ {
+ "name": "Reports",
+ "description": "Reports"
+ },
+ {
+ "name": "SavedSearches",
+ "description": "SavedSearches"
+ },
+ {
+ "name": "Users",
+ "description": "Users"
+ },
+ {
+ "name": "Groups",
+ "description": "Groups"
+ },
+ {
+ "name": "CssSettings",
+ "description": "CssSettings"
+ },
+ {
+ "name": "Environment Variables",
+ "description": "Environment Variables"
+ },
+ {
+ "name": "Files",
+ "description": "Files"
+ },
+ {
+ "name": "Group Members",
+ "description": "Group Members"
+ },
+ {
+ "name": "Notifications",
+ "description": "Notifications"
+ },
+ {
+ "name": "Permissions",
+ "description": "Permissions"
+ },
+ {
+ "name": "Process Categories",
+ "description": "Process Categories"
+ },
+ {
+ "name": "Processes",
+ "description": "Processes"
+ },
+ {
+ "name": "Process Requests",
+ "description": "Process Requests"
+ },
+ {
+ "name": "Request Files",
+ "description": "Request Files"
+ },
+ {
+ "name": "Screen Categories",
+ "description": "Screen Categories"
+ },
+ {
+ "name": "Screens",
+ "description": "Screens"
+ },
+ {
+ "name": "Script Categories",
+ "description": "Script Categories"
+ },
+ {
+ "name": "Scripts",
+ "description": "Scripts"
+ },
+ {
+ "name": "Rebuild Script Executors",
+ "description": "Rebuild Script Executors"
+ },
+ {
+ "name": "Security Logs",
+ "description": "Security Logs"
+ },
+ {
+ "name": "Settings",
+ "description": "Settings"
+ },
+ {
+ "name": "Signals",
+ "description": "Signals"
+ },
+ {
+ "name": "Task Assignments",
+ "description": "Task Assignments"
+ },
+ {
+ "name": "Tasks",
+ "description": "Tasks"
+ },
+ {
+ "name": "Personal Tokens",
+ "description": "Personal Tokens"
+ },
+ {
+ "name": "Processes Variables",
+ "description": "Processes Variables"
+ },
+ {
+ "name": "AnalyticsReporting",
+ "description": "AnalyticsReporting"
+ },
+ {
+ "name": "Collections",
+ "description": "Collections"
+ },
+ {
+ "name": "Comments",
+ "description": "Comments"
+ },
+ {
+ "name": "DataSourcesCategories",
+ "description": "DataSourcesCategories"
+ },
+ {
+ "name": "DataSources",
+ "description": "DataSources"
+ },
+ {
+ "name": "Version History",
+ "description": "Version History"
+ }
+ ],
"security": [
{
"passport": [],
diff --git a/tests/Feature/Api/IntermediateTimerEventTest.php b/tests/Feature/Api/IntermediateTimerEventTest.php
index 5dd772f8a5..64efba1b0b 100644
--- a/tests/Feature/Api/IntermediateTimerEventTest.php
+++ b/tests/Feature/Api/IntermediateTimerEventTest.php
@@ -206,4 +206,44 @@ public function testScheduleIntermediateTimerEventWithMustacheSyntax()
$iteToken->refresh();
$this->assertEquals('CLOSED', $iteToken->status);
}
+
+ public function testScheduleIntermediateTimerEventWithFEELSyntax()
+ {
+ $this->be($this->user);
+ $data = [];
+ $data['bpmn'] = Process::getProcessTemplate('IntermediateTimerEventFEEL.bpmn');
+ $process = Process::factory()->create($data);
+ $definitions = $process->getDefinitions();
+ $startEvent = $definitions->getEvent('_2');
+ // now + 8 minutes
+ $timestamp = time() + 480;
+ // Pass variables to calculate the date and time using FEEL: date ~ "T" ~ time
+ $request = WorkflowManager::triggerStartEvent($process, $startEvent, [
+ 'date' => date('Y-m-d', $timestamp),
+ 'time' => date('H:i:sP', $timestamp)
+ ]);
+ $task1 = $request->tokens()->where('element_id', '_3')->first();
+ WorkflowManager::completeTask($process, $request, $task1, []); // moves to timer event I guess
+
+ // Time travel 5 minutes into the future
+ Carbon::setTestNow(Carbon::now()->addMinute(5));
+
+ // Re-schedule events for artisan call
+ $scheduleManager = new TaskSchedulerManager();
+ $scheduleManager->scheduleTasks();
+ \Artisan::call('schedule:run');
+
+ $iteToken = $request->tokens()->where('element_id', '_5')->firstOrFail();
+ $this->assertEquals('ACTIVE', $iteToken->status); // Not enough time has passed
+
+ // Time travel 5 more minutes into the future
+ Carbon::setTestNow(Carbon::now()->addMinute(5));
+
+ // Re-schedule events for artisan call
+ $scheduleManager->scheduleTasks();
+ \Artisan::call('schedule:run');
+
+ $iteToken->refresh();
+ $this->assertEquals('CLOSED', $iteToken->status);
+ }
}
diff --git a/tests/Feature/Events/EmailEventTest.php b/tests/Feature/Events/EmailEventTest.php
new file mode 100644
index 0000000000..79a37a1e9a
--- /dev/null
+++ b/tests/Feature/Events/EmailEventTest.php
@@ -0,0 +1,480 @@
+request = ProcessRequest::factory()->create([
+ 'id' => $this->requestId,
+ 'status' => 'ACTIVE',
+ ]);
+ }
+
+ /**
+ * Test each email event handler individually
+ */
+ public function testEmailSentHandling()
+ {
+ $this->runEventTest(
+ EmailSent::class,
+ EmailSentEvent::class,
+ 'X-ProcessMaker-Sent-Message-Event-ID'
+ );
+ }
+
+ /**
+ * Test EmailDelivered event handling
+ */
+ public function testEmailDeliveredHandling()
+ {
+ $this->runEventTest(
+ EmailDelivered::class,
+ EmailDeliveredEvent::class,
+ 'X-ProcessMaker-Delivered-Message-Event-ID'
+ );
+ }
+
+ /**
+ * Test EmailComplaint event handling
+ */
+ public function testEmailComplaintHandling()
+ {
+ $this->runEventTest(
+ EmailComplaint::class,
+ ComplaintMessageEvent::class,
+ 'X-ProcessMaker-Complaint-Message-Event-ID'
+ );
+ }
+
+ /**
+ * Test EmailViewed event handling
+ */
+ public function testEmailViewedHandling()
+ {
+ $this->runEventTest(
+ EmailViewed::class,
+ ViewEmailEvent::class,
+ 'X-ProcessMaker-Viewed-Message-Event-ID'
+ );
+ }
+
+ /**
+ * Test EmailLinkClicked event handling
+ */
+ public function testEmailLinkClickedHandling()
+ {
+ $this->runEventTest(
+ EmailLinkClicked::class,
+ LinkClickedEvent::class,
+ 'X-ProcessMaker-Link-Clicked-Message-Event-ID'
+ );
+ }
+
+ /**
+ * Common test runner for all event types
+ */
+ private function runEventTest(string $handlerClass, string $eventClass, string $messageEventIdHeader)
+ {
+ // Create the event handler
+ $handler = new $handlerClass();
+
+ // Set expectations for the WorkflowManager facade
+ WorkflowManager::shouldReceive('triggerMessageEvent')
+ ->once()
+ ->with(Mockery::type(ProcessRequest::class), $this->messageEventId, ['email_id' => $this->emailId])
+ ->andReturnTrue();
+
+ // Create an event mock with appropriate tracker
+ $trackerMock = $this->createTrackerMock($messageEventIdHeader);
+ $eventMock = Mockery::mock($eventClass);
+ $eventMock->sent_email = $trackerMock;
+
+ // Call the handler
+ $handler->handle($eventMock);
+ }
+
+ /**
+ * Test email event header validation for EmailSent
+ */
+ public function testEmailSentHeaderMatch()
+ {
+ $this->runHeaderTest(
+ EmailSent::class,
+ EmailSentEvent::class,
+ 'X-ProcessMaker-Sent-Message-Event-ID'
+ );
+ }
+
+ /**
+ * Test email event header validation for EmailDelivered
+ */
+ public function testEmailDeliveredHeaderMatch()
+ {
+ $this->runHeaderTest(
+ EmailDelivered::class,
+ EmailDeliveredEvent::class,
+ 'X-ProcessMaker-Delivered-Message-Event-ID'
+ );
+ }
+
+ /**
+ * Test email event header validation for EmailComplaint
+ */
+ public function testEmailComplaintHeaderMatch()
+ {
+ $this->runHeaderTest(
+ EmailComplaint::class,
+ ComplaintMessageEvent::class,
+ 'X-ProcessMaker-Complaint-Message-Event-ID'
+ );
+ }
+
+ /**
+ * Test email event header validation for EmailViewed
+ */
+ public function testEmailViewedHeaderMatch()
+ {
+ $this->runHeaderTest(
+ EmailViewed::class,
+ ViewEmailEvent::class,
+ 'X-ProcessMaker-Viewed-Message-Event-ID'
+ );
+ }
+
+ /**
+ * Test email event header validation for EmailLinkClicked
+ */
+ public function testEmailLinkClickedHeaderMatch()
+ {
+ $this->runHeaderTest(
+ EmailLinkClicked::class,
+ LinkClickedEvent::class,
+ 'X-ProcessMaker-Link-Clicked-Message-Event-ID'
+ );
+ }
+
+ /**
+ * Common header test runner for all event types
+ */
+ private function runHeaderTest(string $handlerClass, string $eventClass, string $messageEventIdHeader)
+ {
+ // Create the event handler
+ $handler = new $handlerClass();
+
+ // Create a special tracker mock that will only accept exact header names
+ $trackerMock = Mockery::mock(SentEmail::class);
+
+ $trackerMock->shouldReceive('getHeader')
+ ->with('X-ProcessMaker-Email-ID')
+ ->once()
+ ->andReturn($this->emailId);
+
+ $trackerMock->shouldReceive('getHeader')
+ ->with($messageEventIdHeader)
+ ->once()
+ ->andReturn($this->messageEventId);
+
+ $trackerMock->shouldReceive('getHeader')
+ ->with('X-ProcessMaker-Request-ID')
+ ->once()
+ ->andReturn($this->requestId);
+
+ // Create event mock
+ $eventMock = Mockery::mock($eventClass);
+ $eventMock->sent_email = $trackerMock;
+
+ // Call the handler
+ $handler->handle($eventMock);
+ }
+
+ /**
+ * Test missing process request handling for EmailSent
+ */
+ public function testEmailSentNoProcessRequest()
+ {
+ $this->runMissingRequestTest(
+ EmailSent::class,
+ EmailSentEvent::class,
+ 'X-ProcessMaker-Sent-Message-Event-ID'
+ );
+ }
+
+ /**
+ * Test missing process request handling for EmailDelivered
+ */
+ public function testEmailDeliveredNoProcessRequest()
+ {
+ $this->runMissingRequestTest(
+ EmailDelivered::class,
+ EmailDeliveredEvent::class,
+ 'X-ProcessMaker-Delivered-Message-Event-ID'
+ );
+ }
+
+ /**
+ * Test missing process request handling for EmailComplaint
+ */
+ public function testEmailComplaintNoProcessRequest()
+ {
+ $this->runMissingRequestTest(
+ EmailComplaint::class,
+ ComplaintMessageEvent::class,
+ 'X-ProcessMaker-Complaint-Message-Event-ID'
+ );
+ }
+
+ /**
+ * Test missing process request handling for EmailViewed
+ */
+ public function testEmailViewedNoProcessRequest()
+ {
+ $this->runMissingRequestTest(
+ EmailViewed::class,
+ ViewEmailEvent::class,
+ 'X-ProcessMaker-Viewed-Message-Event-ID'
+ );
+ }
+
+ /**
+ * Test missing process request handling for EmailLinkClicked
+ */
+ public function testEmailLinkClickedNoProcessRequest()
+ {
+ $this->runMissingRequestTest(
+ EmailLinkClicked::class,
+ LinkClickedEvent::class,
+ 'X-ProcessMaker-Link-Clicked-Message-Event-ID'
+ );
+ }
+
+ /**
+ * Common test runner for missing process request scenarios
+ */
+ private function runMissingRequestTest(string $handlerClass, string $eventClass, string $messageEventIdHeader)
+ {
+ // Delete the process request to simulate it not being found
+ $this->request->delete();
+
+ // Create the event handler
+ $handler = new $handlerClass();
+
+ // WorkflowManager should NOT be called when request isn't found
+ WorkflowManager::shouldReceive('triggerMessageEvent')->never();
+
+ // Create event mock with normal tracker
+ $trackerMock = $this->createTrackerMock($messageEventIdHeader);
+ $eventMock = Mockery::mock($eventClass);
+ $eventMock->sent_email = $trackerMock;
+
+ // Call the handler - should not error when no request found
+ $handler->handle($eventMock);
+ }
+
+ /**
+ * Test missing headers handling for EmailSent
+ */
+ public function testEmailSentMissingHeaders()
+ {
+ $this->runMissingHeadersTest(
+ EmailSent::class,
+ EmailSentEvent::class,
+ 'X-ProcessMaker-Sent-Message-Event-ID'
+ );
+ }
+
+ /**
+ * Test missing headers handling for EmailDelivered
+ */
+ public function testEmailDeliveredMissingHeaders()
+ {
+ $this->runMissingHeadersTest(
+ EmailDelivered::class,
+ EmailDeliveredEvent::class,
+ 'X-ProcessMaker-Delivered-Message-Event-ID'
+ );
+ }
+
+ /**
+ * Test missing headers handling for EmailComplaint
+ */
+ public function testEmailComplaintMissingHeaders()
+ {
+ $this->runMissingHeadersTest(
+ EmailComplaint::class,
+ ComplaintMessageEvent::class,
+ 'X-ProcessMaker-Complaint-Message-Event-ID'
+ );
+ }
+
+ /**
+ * Test missing headers handling for EmailViewed
+ */
+ public function testEmailViewedMissingHeaders()
+ {
+ $this->runMissingHeadersTest(
+ EmailViewed::class,
+ ViewEmailEvent::class,
+ 'X-ProcessMaker-Viewed-Message-Event-ID'
+ );
+ }
+
+ /**
+ * Test missing headers handling for EmailLinkClicked
+ */
+ public function testEmailLinkClickedMissingHeaders()
+ {
+ $this->runMissingHeadersTest(
+ EmailLinkClicked::class,
+ LinkClickedEvent::class,
+ 'X-ProcessMaker-Link-Clicked-Message-Event-ID'
+ );
+ }
+
+ /**
+ * Common test runner for missing headers scenarios
+ */
+ private function runMissingHeadersTest(string $handlerClass, string $eventClass, string $messageEventIdHeader)
+ {
+ // Create the event handler
+ $handler = new $handlerClass();
+
+ // WorkflowManager should NOT be called when headers missing
+ WorkflowManager::shouldReceive('triggerMessageEvent')->never();
+
+ // Create tracker mock with missing header
+ $trackerMock = Mockery::mock(SentEmail::class);
+ $trackerMock->shouldReceive('getHeader')
+ ->with('X-ProcessMaker-Email-ID')
+ ->andReturn($this->emailId);
+ $trackerMock->shouldReceive('getHeader')
+ ->with($messageEventIdHeader)
+ ->andReturn(null); // Missing header!
+ $trackerMock->shouldReceive('getHeader')
+ ->with('X-ProcessMaker-Request-ID')
+ ->andReturn($this->requestId);
+
+ // Create event mock
+ $eventMock = Mockery::mock($eventClass);
+ $eventMock->sent_email = $trackerMock;
+
+ // Call the handler - should not error when header missing
+ $handler->handle($eventMock);
+ }
+
+ /**
+ * Helper method to create a tracker mock with standard headers
+ */
+ protected function createTrackerMock(string $messageEventIdHeader)
+ {
+ $trackerMock = Mockery::mock(SentEmail::class);
+ $trackerMock->shouldReceive('getHeader')
+ ->with('X-ProcessMaker-Email-ID')
+ ->andReturn($this->emailId);
+ $trackerMock->shouldReceive('getHeader')
+ ->with($messageEventIdHeader)
+ ->andReturn($this->messageEventId);
+ $trackerMock->shouldReceive('getHeader')
+ ->with('X-ProcessMaker-Request-ID')
+ ->andReturn($this->requestId);
+
+ return $trackerMock;
+ }
+
+ /**
+ * Test that emails without tracking enabled don't generate warning logs
+ */
+ public function testEmailWithoutTrackingEnabled()
+ {
+ // Mock the Log facade using Laravel's built-in support
+ Log::shouldReceive('debug')
+ ->withAnyArgs()
+ ->atLeast(0);
+
+ Log::shouldReceive('error')
+ ->withAnyArgs()
+ ->atLeast(0);
+
+ // The important part - we should not see warnings about missing headers
+ // when no tracking headers are present
+ Log::shouldReceive('warning')
+ ->with(Mockery::pattern('/.*missing required headers.*/'), Mockery::any())
+ ->never();
+
+ // Create an event handler (using EmailSent as an example)
+ $handler = new EmailSent();
+
+ // Create tracker mock with no tracking headers
+ $trackerMock = Mockery::mock(SentEmail::class);
+ $trackerMock->shouldReceive('getHeader')
+ ->with('X-ProcessMaker-Email-ID')
+ ->andReturn(null); // No email ID header = tracking not enabled
+ $trackerMock->shouldReceive('getHeader')
+ ->with('X-ProcessMaker-Sent-Message-Event-ID')
+ ->andReturn(null);
+ $trackerMock->shouldReceive('getHeader')
+ ->with('X-ProcessMaker-Request-ID')
+ ->andReturn(null);
+
+ // Create event mock
+ $eventMock = Mockery::mock(EmailSentEvent::class);
+ $eventMock->sent_email = $trackerMock;
+
+ // WorkflowManager should NOT be called when tracking not enabled
+ WorkflowManager::shouldReceive('triggerMessageEvent')->never();
+
+ // Call the handler - this should not throw an exception
+ $handler->handle($eventMock);
+ }
+
+ /**
+ * Clean up after each test
+ */
+ protected function tearDown(): void
+ {
+ parent::tearDown();
+ Mockery::close();
+ }
+}