diff --git a/app/Dto/ChartDataPoint.php b/app/Dto/ChartDataPoint.php new file mode 100644 index 0000000..98889c1 --- /dev/null +++ b/app/Dto/ChartDataPoint.php @@ -0,0 +1,25 @@ + $this->x, + 'y' => [$this->yMin, $this->yMax], + 'type' => $this->type, + ]; + } +} diff --git a/app/Http/Controllers/WorkflowsController.php b/app/Http/Controllers/WorkflowsController.php index 1e90e19..484a7a7 100644 --- a/app/Http/Controllers/WorkflowsController.php +++ b/app/Http/Controllers/WorkflowsController.php @@ -3,6 +3,8 @@ namespace Waterline\Http\Controllers; use SplFileObject; +use Waterline\Http\Resources\StoredWorkflowResource; +use Waterline\Transformer\WorkflowToChartDataTransformer; use Workflow\Models\StoredWorkflow; use Workflow\Serializers\Y; @@ -34,36 +36,6 @@ public function running() { public function show($id) { $flow = config('workflows.stored_workflow_model', StoredWorkflow::class)::with(['exceptions', 'logs'])->find($id); - $flow->arguments = serialize(Y::unserialize($flow->arguments)); - - $flow->logs = $flow->logs->map(function ($log) { - $log->result = serialize(Y::unserialize($log->result)); - return $log; - }); - - $flow->exceptions = $flow->exceptions->map(function ($exception) { - $exception->code ??= null; - $unserialized = Y::unserialize($exception->exception); - if (is_array($unserialized) - && array_key_exists('class', $unserialized) - && is_subclass_of($unserialized['class'], \Throwable::class) - && file_exists($unserialized['file']) - ) { - $file = new SplFileObject($unserialized['file']); - $file->seek($unserialized['line'] - 4); - for ($line = 0; $line < 7; ++$line) { - $exception->code .= $file->current(); - $file->next(); - if ($file->eof()) break; - } - $exception->code = rtrim($exception->code); - $exception->exception = serialize($unserialized); - } - return $exception; - }); - - $flow->output = $flow->output === null ? serialize(null) : serialize(Y::unserialize($flow->output)); - - return $flow; + return StoredWorkflowResource::make($flow); } } diff --git a/app/Http/Resources/StoredWorkflowExceptionResource.php b/app/Http/Resources/StoredWorkflowExceptionResource.php new file mode 100644 index 0000000..cbc4bbd --- /dev/null +++ b/app/Http/Resources/StoredWorkflowExceptionResource.php @@ -0,0 +1,50 @@ +exception; + + $unserialized = Y::unserialize($exception); + if (is_array($unserialized) + && array_key_exists('class', $unserialized) + && is_subclass_of($unserialized['class'], \Throwable::class) + && file_exists($unserialized['file']) + ) { + $file = new SplFileObject($unserialized['file']); + $file->seek($unserialized['line'] - 4); + for ($line = 0; $line < 7; ++$line) { + $exception->code .= $file->current(); + $file->next(); + if ($file->eof()) break; + } + $code = rtrim($exception->code); + $exception = serialize($unserialized); + } + + return [ + "code" => $code, + "exception" => $exception, + "class" => $this->class, + "created_at" => $this->created_at, + ]; + } +} diff --git a/app/Http/Resources/StoredWorkflowLogResource.php b/app/Http/Resources/StoredWorkflowLogResource.php new file mode 100644 index 0000000..3fdcc8c --- /dev/null +++ b/app/Http/Resources/StoredWorkflowLogResource.php @@ -0,0 +1,31 @@ + $this->id, + "index" => $this->index, + "now" => $this->now, + "class" => $this->class, + "result" => serialize(Y::unserialize($this->result)), + "created_at" => $this->created_at, + ]; + } +} diff --git a/app/Http/Resources/StoredWorkflowResource.php b/app/Http/Resources/StoredWorkflowResource.php new file mode 100644 index 0000000..e3ccca5 --- /dev/null +++ b/app/Http/Resources/StoredWorkflowResource.php @@ -0,0 +1,34 @@ + $this->id, + "class" => $this->class, + "arguments" => serialize(Y::unserialize($this->arguments)), + "output" => $this->output === null ? serialize(null) : serialize(Y::unserialize($this->output)), + "status" => $this->status, + "created_at" => $this->created_at, + "updated_at" => $this->updated_at, + "logs" => StoredWorkflowLogResource::collection($this->logs), + "exceptions" => StoredWorkflowExceptionResource::collection($this->exceptions), + "chartData" => app(WorkflowToChartDataTransformer::class)->transform($this->resource), + ]; + } +} diff --git a/app/Transformer/WorkflowToChartDataTransformer.php b/app/Transformer/WorkflowToChartDataTransformer.php new file mode 100644 index 0000000..958b495 --- /dev/null +++ b/app/Transformer/WorkflowToChartDataTransformer.php @@ -0,0 +1,70 @@ +transformWorkflow($storedWorkflow); + + foreach ($storedWorkflow->children as $childWorkflow) { + $data = array_merge( + $data, + $this->transform($childWorkflow), + ); + } + + return $data; + } + + /** + * @return ChartDataPoint[] + */ + private function transformWorkflow(StoredWorkflow $storedWorkflow) : array { + $data = [ + app(ChartDataPoint::class, [ + 'x' => $storedWorkflow->class, + 'yMin' => (float) $storedWorkflow->created_at->isoFormat('XSSS'), + 'yMax' => (float) $storedWorkflow->updated_at->isoFormat('XSSS'), + 'type' => 'Workflow' + ]) + ]; + + $prevLogCreated = $storedWorkflow->created_at; + foreach ($storedWorkflow->logs as $log) { + if (is_subclass_of($log->class, Workflow::class)) { + continue; + } + + $data[] = $this->transformLog($log, $prevLogCreated); + $prevLogCreated = $log->created_at; + } + + return $data; + } + + /** + * @return ChartDataPoint + */ + private function transformLog(StoredWorkflowLog $storedWorkflowLog, CarbonInterface $prevLogCreated) : ChartDataPoint { + + return app(ChartDataPoint::class, [ + 'x' => $storedWorkflowLog->class, + 'yMin' => (float) $prevLogCreated->isoFormat('XSSS'), + 'yMax' => (float) $storedWorkflowLog->created_at->isoFormat('XSSS'), + 'type' => 'Activity', + ]); + } +} diff --git a/public/app.js b/public/app.js index 1fce108..7a89263 100644 --- a/public/app.js +++ b/public/app.js @@ -2280,7 +2280,7 @@ function _typeof(obj) { "@babel/helpers - typeof"; return _typeof = "function" = w = _ref.w; if (seriesIndex === 0) { var data = w.globals.initialSeries[seriesIndex].data[dataPointIndex]; - return '
' + 'Activity: ' + data.x.split('_')[0] + '
' + 'Time: ' + (data.y[1] - data.y[0]) + 'ms
'; + return '
' + '' + data.type + ': ' + data.x.split('_')[0] + '
' + 'Time: ' + (data.y[1] - data.y[0]) + 'ms
'; } if (seriesIndex === 1) { var exception = phpunserialize__WEBPACK_IMPORTED_MODULE_0___default()(_this.flow.exceptions[dataPointIndex].exception); @@ -2332,12 +2332,7 @@ function _typeof(obj) { "@babel/helpers - typeof"; return _typeof = "function" = this.ready = false; this.$http.get(Waterline.basePath + '/api/flows/' + id).then(function (response) { _this2.flow = response.data; - _this2.series[0].data = _this2.flow.logs.map(function (activity, index, activities) { - return { - x: activity["class"], - y: [index === 0 ? moment_timezone__WEBPACK_IMPORTED_MODULE_1___default()(_this2.flow.created_at).valueOf() : moment_timezone__WEBPACK_IMPORTED_MODULE_1___default()(activities[index - 1].created_at).valueOf(), moment_timezone__WEBPACK_IMPORTED_MODULE_1___default()(activity.created_at).valueOf()] - }; - }); + _this2.series[0].data = response.data.chartData; _this2.series[1].data = _this2.flow.exceptions.map(function (exception) { _this2.$nextTick(function () { _this2.$nextTick(function () { diff --git a/public/mix-manifest.json b/public/mix-manifest.json index b351b62..1bd119e 100644 --- a/public/mix-manifest.json +++ b/public/mix-manifest.json @@ -1,5 +1,5 @@ { - "/app.js": "/app.js?id=ad4fe9437176e22cd21076e124a481f3", + "/app.js": "/app.js?id=d8462d5df178a947e8a71869b5ea1018", "/app-dark.css": "/app-dark.css?id=3e8dddb1d146175eb19d916f9cd87bfa", "/app.css": "/app.css?id=12fca36d651455c3d460d9c4abf772c5", "/img/favicon.png": "/img/favicon.png?id=7c006241b093796d6abfa3049df93a59", diff --git a/resources/js/screens/flows/flow.vue b/resources/js/screens/flows/flow.vue index bc4ac37..2f7fd01 100644 --- a/resources/js/screens/flows/flow.vue +++ b/resources/js/screens/flows/flow.vue @@ -233,7 +233,7 @@ export default { let data = w.globals.initialSeries[seriesIndex].data[dataPointIndex] return '
' + - 'Activity: ' + data.x.split('_')[0] + '
' + + ''+data.type+': ' + data.x.split('_')[0] + '
' + 'Time: ' + (data.y[1] - data.y[0]) + 'ms
' } if (seriesIndex === 1) { @@ -298,16 +298,7 @@ export default { this.$http.get(Waterline.basePath + '/api/flows/' + id) .then(response => { this.flow = response.data; - this.series[0].data = this.flow.logs.map((activity, index, activities) => { - return { - x: activity.class, - y: [ - index === 0 ? moment(this.flow.created_at).valueOf() : moment(activities[index - 1].created_at).valueOf(), - moment(activity.created_at).valueOf(), - ], - } - }) - + this.series[0].data = response.data.chartData; this.series[1].data = this.flow.exceptions.map((exception) => { this.$nextTick(() => { this.$nextTick(() => { @@ -331,7 +322,7 @@ export default { ], fillColor: '#721c24', } - }) + }); this.ready = true; });