Skip to content

Commit b86f507

Browse files
(v2.8) adds events timeline
1 parent 357fc3e commit b86f507

File tree

5 files changed

+108
-29
lines changed

5 files changed

+108
-29
lines changed

src/LaravelRequestDocsMiddleware.php

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@ class LaravelRequestDocsMiddleware extends QueryLogger
1515
private array $queries = [];
1616
private array $logs = [];
1717
private array $models = [];
18+
private array $modelsTimeline = [];
1819

1920
public function handle($request, Closure $next)
2021
{
@@ -46,6 +47,8 @@ public function handle($request, Closure $next)
4647
'queries' => $this->queries,
4748
'logs' => $this->logs,
4849
'models' => $this->models,
50+
// 'modelsTimeline' => $this->modelsTimeline,
51+
'modelsTimeline' => array_unique($this->modelsTimeline, SORT_REGULAR),
4952
'memory' => (string) round(memory_get_peak_usage(true) / 1048576, 2) . "MB",
5053
];
5154
$jsonContent = json_encode($content);
@@ -82,6 +85,7 @@ public function listenToModels()
8285
foreach (array_filter($models) as $model) {
8386
// doing and booted ignore
8487
if (Str::startsWith($event, 'eloquent.booting')
88+
|| Str::startsWith($event, 'eloquent.booted')
8589
|| Str::startsWith($event, 'eloquent.retrieving')
8690
|| Str::startsWith($event, 'eloquent.creating')
8791
|| Str::startsWith($event, 'eloquent.saving')
@@ -95,6 +99,11 @@ public function listenToModels()
9599
$event = Str::replace('eloquent.', '', $event);
96100
$class = get_class($model);
97101

102+
$this->modelsTimeline[] = [
103+
'event' => $event,
104+
'model' => $class,
105+
];
106+
98107
if (!isset($this->models[$class])) {
99108
$this->models[$class] = [];
100109
}

ui/src/components/ApiAction.tsx

Lines changed: 10 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -33,12 +33,15 @@ export default function ApiAction(props: Props) {
3333
const [responseData, setResponseData] = useState("");
3434
const [sqlQueriesCount, setSqlQueriesCount] = useState(0);
3535
const [sqlData, setSqlData] = useState("");
36-
const [modelsData, setModelsData] = useState({});
36+
const [modelsData, setModelsData] = useState({
37+
modelsSummary: [],
38+
modelsTimeline: []
39+
});
3740
const [logsData, setLogsData] = useState("");
3841
const [serverMemory, setServerMemory] = useState("");
3942
const [responseStatus, setResponseStatus] = useState(0);
4043
const [responseHeaders, setResponseHeaders] = useState("");
41-
const [activeTab, setActiveTab] = useState('info');
44+
const [activeTab, setActiveTab] = useState('events');
4245

4346
const handleFileChange = (files: any, file: any) => {
4447
const formData: any = new FormData()
@@ -151,8 +154,11 @@ export default function ApiAction(props: Props) {
151154
if (data && data._lrd && data._lrd.memory) {
152155
setServerMemory(data._lrd.memory)
153156
}
154-
if (data && data._lrd && data._lrd.models) {
155-
setModelsData(data._lrd.models)
157+
if (data && data._lrd && data._lrd.models && data._lrd.modelsTimeline) {
158+
setModelsData({
159+
modelsSummary: data._lrd.models,
160+
modelsTimeline: data._lrd.modelsTimeline
161+
})
156162
}
157163
// remove key _lrd from response
158164
if (data && data._lrd) {

ui/src/components/ApiInfo.tsx

Lines changed: 9 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -74,9 +74,12 @@ export default function ApiInfo(props: Props) {
7474
}
7575
if (keyPart == 'regex') {
7676
return (
77-
<div className="block">
78-
Match: <code>${valuePart}</code>
79-
</div>
77+
<>
78+
<div className="inline-block badge badge-info badge-outline mt-1 mb-1 mr-2 rounded-sm">
79+
Regexp
80+
</div>
81+
<code>${valuePart}</code>
82+
</>
8083
)
8184
}
8285

@@ -112,13 +115,9 @@ export default function ApiInfo(props: Props) {
112115
<span className='text-blue-500 pr-1'>¬</span>
113116
<code className='pl-1'>
114117
{key}
115-
{lrdDocsItem.rules[key].map((rule) => (
116-
rule.split('|').map((theRule) => (
117-
(theRule == "array" || key.endsWith(".*")) ? (
118-
<ChevronRightIcon key={shortid.generate()} className='inline-block w-4 h-4' />
119-
) : (<span key={shortid.generate()}></span>)
120-
))
121-
))}
118+
{(key.endsWith(".*")) ? (
119+
<ChevronRightIcon key={shortid.generate()} className='inline-block w-4 h-4' />
120+
) : (<span key={shortid.generate()}></span>)}
122121
</code>
123122
{lrdDocsItem.rules[key].map((rule) => (
124123
rule.split('|').map((theRule) => (
Lines changed: 46 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1,47 +1,46 @@
11
import React from 'react';
22

33
import { explode } from '../../libs/strings'
4+
import shortid from 'shortid';
45

56
interface Props {
67
modelsData: any,
78
}
89

910
export default function ApiActionEvents(props: Props) {
1011
const { modelsData } = props
12+
const { modelsSummary, modelsTimeline } = modelsData
1113

1214
return (
1315
<>
14-
{!Object.keys(modelsData).length && (
16+
{!Object.keys(modelsSummary).length && (
1517
<div className='text-center text-sm text-slate-500'>
1618
No Models Data
1719
</div>
1820
)}
19-
{Object.keys(modelsData).length != 0 && (
21+
{Object.keys(modelsSummary).length != 0 && (
2022
<>
21-
<h3 className='title'>Models</h3>
22-
<p>
23-
<small className='text-slate-500'>Events are in the order of occurances</small>
24-
</p>
23+
<h3 className='title'>Model events Summary</h3>
2524
<div className='divider'></div>
26-
{Object.keys(modelsData).map((model, index) => {
25+
{Object.keys(modelsSummary).map((model) => {
2726
return (
28-
<table className='table table-compact table-fixed table-zebra w-full mb-10' key={index}>
27+
<table className='table table-compact table-fixed table-zebra w-full mb-10' key={shortid.generate()}>
2928
<tbody>
30-
{Object.keys(modelsData[model]).map((event, idx) => {
29+
{Object.keys(modelsSummary[model]).map((event, idx) => {
3130
return (
32-
<tr key={idx}>
31+
<tr key={shortid.generate()}>
3332
{idx == 0 && (
34-
<td rowSpan={Object.keys(modelsData[model]).length}>
33+
<td rowSpan={Object.keys(modelsSummary[model]).length}>
3534
<span className='font-bold text-slate-500'>Model</span>
3635
<br />
3736
<div className='' dangerouslySetInnerHTML={{ __html: explode(model.split('\\')[model.split('\\').length - 1], 30, "<br/>") }} />
3837
</td>
3938
)}
4039
<td className='capitalize'>{event}</td>
4140
<td>
42-
<span className='font-bold'>{modelsData[model][event]}</span>
41+
<span className='font-bold'>{modelsSummary[model][event]}</span>
4342
<span className='text-slate-400 pl-1'>
44-
Time{modelsData[model][event] > 1 ? 's' : ''}
43+
Time{modelsSummary[model][event] > 1 ? 's' : ''}
4544
</span>
4645
</td>
4746
</tr>
@@ -53,6 +52,40 @@ export default function ApiActionEvents(props: Props) {
5352
})}
5453
</>
5554
)}
55+
56+
{Object.keys(modelsTimeline).length != 0 && (
57+
<>
58+
<h3 className='title'>Model Events Timeline</h3>
59+
<small className='text-slate-500'>Events are in the order of occurances</small>
60+
<div className='divider'></div>
61+
<div className="flex flex-col md:grid grid-cols-12">
62+
{Object.keys(modelsTimeline).map((index) => {
63+
return (
64+
<div className="flex md:contents" key={shortid.generate()}>
65+
<div className="col-start-2 col-end-4 mr-10 md:mx-auto relative">
66+
<div className="h-full w-3 flex items-center justify-center">
67+
<div className={`h-full w-1 bg-${modelsTimeline[index].event} pointer-events-none`}></div>
68+
</div>
69+
<div className={`w-3 h-3 absolute top-1/2 rounded-full bg-${modelsTimeline[index].event} shadow text-center`}>
70+
<i className="fas fa-check-circle text-white"></i>
71+
</div>
72+
</div>
73+
<div className="col-start-4 col-end-12 rounded-md my-3 mr-auto w-full break-all">
74+
<h3 className="mb-1">
75+
<div className='' dangerouslySetInnerHTML={{ __html: explode(modelsTimeline[index].model.split('\\')[modelsTimeline[index].model.split('\\').length - 1], 30, "<br/>") }} />
76+
</h3>
77+
<p className="title text-justify w-full">
78+
<span className={`badge badge-${modelsTimeline[index].event} rounded-sm`}>
79+
{ modelsTimeline[index].event}
80+
</span>
81+
</p>
82+
</div>
83+
</div>
84+
)
85+
})}
86+
</div>
87+
</>
88+
)}
5689
</>
5790
)
5891
}

ui/src/global.css

Lines changed: 34 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -71,10 +71,42 @@ td {
7171
.method-HEAD {
7272
@apply text-info;
7373
}
74-
.badge-200,.badge-201,.badge-202,.response-204 {
74+
.bg-created {
7575
@apply bg-success;
7676
}
77-
.badge-422,.badge-429 {
77+
.bg-saved {
78+
@apply bg-info;
79+
}
80+
.bg-updated {
81+
@apply bg-warning;
82+
}
83+
.bg-deleted {
84+
@apply bg-error;
85+
}
86+
.bg-retrieved {
87+
@apply bg-gray-800;
88+
}
89+
.badge-created {
90+
@apply badge-success;
91+
}
92+
.badge-saved {
93+
@apply badge-info;
94+
}
95+
.badge-updated {
96+
@apply badge-warning;
97+
}
98+
.badge-deleted {
99+
@apply badge-error;
100+
}
101+
.badge-retrieved {
102+
@apply badge-ghost;
103+
}
104+
105+
.badge-200,.badge-201,.badge-202,.response-204, {
106+
@apply bg-success;
107+
}
108+
109+
.badge-422,.badge-429, {
78110
@apply bg-warning;
79111
}
80112
.badge-400,.badge-401,.badge-402,.badge-403,.badge-404,.badge-405 {

0 commit comments

Comments
 (0)