Skip to content

Commit 4033420

Browse files
committed
added pagiantion and date filter to webhook attempts component
1 parent d160b4d commit 4033420

3 files changed

Lines changed: 231 additions & 100 deletions

File tree

Lines changed: 112 additions & 96 deletions
Original file line numberDiff line numberDiff line change
@@ -1,106 +1,122 @@
11
<div class="content-panel" ...attributes>
22
<div class="content-panel-header">
3-
<div class="flex items-center">
4-
<div>
5-
<h3 class="mb-1 mr-4 text-xl font-bold dark:text-gray-100">
6-
{{t "developers.component.webhook.attempts.webhook-header"}}
7-
</h3>
8-
<p class="dark:text-gray-100 text-sm">
9-
{{t "developers.component.webhook.attempts.webhook-message"}}
10-
</p>
3+
<div class="flex-1">
4+
<div class="flex items-center mb-4">
5+
<div>
6+
<h3 class="mb-1 mr-4 text-xl font-bold dark:text-gray-100">
7+
{{t "developers.component.webhook.attempts.webhook-header"}}
8+
</h3>
9+
<p class="dark:text-gray-100 text-sm">
10+
{{t "developers.component.webhook.attempts.webhook-message"}}
11+
</p>
12+
</div>
1113
</div>
12-
</div>
13-
14-
<div class="flex items-center section-header-actions">
15-
<div class="rounded-lg border borer-gray-300 dark:border-gray-700 shadow-sm">
16-
<div class="rounded-lg flex items-center justify-between px-2 py-1 text-sm bg-white dark:bg-gray-900">
17-
<a href="javascript:;" class="mx-4 no-underline text-gray-400 {{unless this.attemptStatus 'font-semibold text-blue-400'}}" {{on "click" this.changeAttemptStatus}}>
18-
{{t "developers.common.all"}}
19-
</a>
20-
<a
21-
href="javascript:;"
22-
class="mx-4 no-underline text-gray-400 {{if (eq this.attemptStatus 'successful') 'font-semibold text-blue-400'}}"
23-
{{on "click" (fn this.changeAttemptStatus "successful")}}
24-
>
25-
{{t "developers.common.succeeded"}}
26-
</a>
27-
<a
28-
href="javascript:;"
29-
class="mx-4 no-underline text-gray-400 {{if (eq this.attemptStatus 'failed') 'font-semibold text-blue-400'}}"
30-
{{on "click" (fn this.changeAttemptStatus "failed")}}
31-
>
32-
{{t "developers.common.failed"}}
33-
</a>
14+
<div class="flex items-center section-header-actions space-x-2">
15+
<div class="rounded-lg border borer-gray-300 dark:border-gray-700 shadow-sm">
16+
<div class="rounded-lg flex items-center justify-between px-2 py-1 text-sm bg-white dark:bg-gray-900">
17+
<a href="javascript:;" class="mx-4 no-underline {{unless this.attemptStatus 'font-semibold text-blue-400' 'text-gray-400'}}" {{on "click" this.changeAttemptStatus}}>
18+
{{t "developers.common.all"}}
19+
</a>
20+
<a
21+
href="javascript:;"
22+
class="mx-4 no-underline {{if (eq this.attemptStatus 'successful') 'font-semibold text-blue-400' 'text-gray-400'}}"
23+
{{on "click" (fn this.changeAttemptStatus "successful")}}
24+
>
25+
{{t "developers.common.succeeded"}}
26+
</a>
27+
<a
28+
href="javascript:;"
29+
class="mx-4 no-underline {{if (eq this.attemptStatus 'failed') 'font-semibold text-blue-400' 'text-gray-400'}}"
30+
{{on "click" (fn this.changeAttemptStatus "failed")}}
31+
>
32+
{{t "developers.common.failed"}}
33+
</a>
34+
</div>
35+
</div>
36+
<div class="rounded-lg border borer-gray-300 dark:border-gray-700 shadow-sm">
37+
<div class="webhook-attempts-date-filter-container">
38+
<div class="date-filter-label">Filter by date:</div>
39+
<DatePicker @value={{this.date}} @onSelect={{this.filterByDate}} placeholder="Filter by date" class="form-input-sm" />
40+
{{#if this.date}}
41+
<Button @type="link" @icon="times" @helpText="Clear date" @onClick={{this.clearDate}} />
42+
{{/if}}
43+
</div>
3444
</div>
3545
</div>
3646
</div>
47+
<div class="flex-1">
48+
{{#if this.webhookRequestLogs.meta}}
49+
<Pagination
50+
@meta={{this.webhookRequestLogs.meta}}
51+
@currentPage={{this.page}}
52+
@onPageChange={{this.changePage}}
53+
@isLoading={{this.getWebhookRequestLogs.isRunning}}
54+
@metaInfoClass="hidden"
55+
class="webhook-attempts-pagination"
56+
/>
57+
{{/if}}
58+
</div>
3759
</div>
3860
<div class="content-panel-body table-wrapper table-fluid">
39-
{{#if this.getWebhookRequestLogs.isRunning}}
40-
<div class="p-4 flex">
41-
<Spinner />
42-
</div>
43-
{{else}}
44-
<Table @rows={{this.webhookRequestLogs}} @columns={{this.columns}} @canExpand={{true}} as |Table|>
45-
<Table.head />
46-
<Table.body as |body|>
47-
<body.expanded-row as |row|>
48-
<table class="border-none table-fixed sub-table dark:text-gray-100 table-spaced-y-2 table-cells-valign-top">
49-
<tbody>
50-
<tr>
51-
<td class="w-64">
52-
{{t "developers.component.webhook.attempts.http-code"}}
53-
</td>
54-
<td>
55-
{{row.status_code}}
56-
({{row.reason_phrase}})
57-
</td>
58-
</tr>
59-
<tr>
60-
<td class="w-64">
61-
{{t "developers.component.webhook.attempts.response-time"}}
62-
</td>
63-
<td>
64-
{{format-milliseconds row.duration}}
65-
</td>
66-
</tr>
67-
<tr>
68-
<td>
69-
{{t "developers.component.webhook.attempts.request-endpoint"}}
70-
</td>
71-
<td>
72-
{{#if row.api_event.data}}
73-
<CodeBlock @code={{or (json-stringify row.api_event.data) ""}} @language="json" class="line-numbers" />
74-
{{else}}
75-
<div class="flex items-center justify-center h-24">
76-
<span class="text-sm text-gray-600">
77-
{{t "developers.component.webhook.attempts.no-request-body"}}
78-
</span>
79-
</div>
80-
{{/if}}
81-
</td>
82-
</tr>
83-
<tr>
84-
<td>
85-
{{t "developers.component.webhook.attempts.response"}}
86-
</td>
87-
<td>
88-
{{#if row.response}}
89-
<CodeBlock @code={{or (json-stringify row.response) ""}} @language="json" class="line-numbers" />
90-
{{else}}
91-
<div class="flex items-center justify-center h-24">
92-
<span class="text-sm text-gray-600">
93-
{{t "developers.component.webhook.attempts.no-response-body"}}
94-
</span>
95-
</div>
96-
{{/if}}
97-
</td>
98-
</tr>
99-
</tbody>
100-
</table>
101-
</body.expanded-row>
102-
</Table.body>
103-
</Table>
104-
{{/if}}
61+
<Table @rows={{this.webhookRequestLogs}} @columns={{this.columns}} @canExpand={{true}} as |Table|>
62+
<Table.head />
63+
<Table.body as |body|>
64+
<body.expanded-row as |row|>
65+
<table class="border-none table-fixed sub-table dark:text-gray-100 table-spaced-y-2 table-cells-valign-top">
66+
<tbody>
67+
<tr>
68+
<td class="w-64">
69+
{{t "developers.component.webhook.attempts.http-code"}}
70+
</td>
71+
<td>
72+
{{row.status_code}}
73+
({{row.reason_phrase}})
74+
</td>
75+
</tr>
76+
<tr>
77+
<td class="w-64">
78+
{{t "developers.component.webhook.attempts.response-time"}}
79+
</td>
80+
<td>
81+
{{format-milliseconds row.duration}}
82+
</td>
83+
</tr>
84+
<tr>
85+
<td>
86+
{{t "developers.component.webhook.attempts.request-endpoint"}}
87+
</td>
88+
<td>
89+
{{#if row.api_event.data}}
90+
<CodeBlock @code={{or (json-stringify row.api_event.data) ""}} @language="json" class="line-numbers" />
91+
{{else}}
92+
<div class="flex items-center justify-center h-24">
93+
<span class="text-sm text-gray-600">
94+
{{t "developers.component.webhook.attempts.no-request-body"}}
95+
</span>
96+
</div>
97+
{{/if}}
98+
</td>
99+
</tr>
100+
<tr>
101+
<td>
102+
{{t "developers.component.webhook.attempts.response"}}
103+
</td>
104+
<td>
105+
{{#if row.response}}
106+
<CodeBlock @code={{or (json-stringify row.response) ""}} @language="json" class="line-numbers" />
107+
{{else}}
108+
<div class="flex items-center justify-center h-24">
109+
<span class="text-sm text-gray-600">
110+
{{t "developers.component.webhook.attempts.no-response-body"}}
111+
</span>
112+
</div>
113+
{{/if}}
114+
</td>
115+
</tr>
116+
</tbody>
117+
</table>
118+
</body.expanded-row>
119+
</Table.body>
120+
</Table>
105121
</div>
106122
</div>

addon/components/webhook/attempts.js

Lines changed: 73 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -5,14 +5,22 @@ import { action } from '@ember/object';
55
import { task } from 'ember-concurrency';
66
import copyToClipboard from '@fleetbase/ember-core/utils/copy-to-clipboard';
77

8+
function filterParams(obj) {
9+
// eslint-disable-next-line no-unused-vars
10+
return Object.fromEntries(Object.entries(obj).filter(([_, value]) => value !== null && value !== undefined));
11+
}
12+
813
export default class WebhookAttemptsComponent extends Component {
914
@service store;
1015
@service intl;
1116
@service hostRouter;
1217
@service notifications;
18+
@service urlSearchParams;
1319
@tracked attemptStatus = null;
1420
@tracked webhookRequestLogs = [];
1521
@tracked webhook;
22+
@tracked page = 1;
23+
@tracked date = null;
1624

1725
/**
1826
* All columns applicable for orders
@@ -68,18 +76,77 @@ export default class WebhookAttemptsComponent extends Component {
6876
constructor(owner, { webhook }) {
6977
super(...arguments);
7078
this.webhook = webhook;
79+
this.restoreParams();
7180
this.getWebhookRequestLogs.perform();
7281
}
7382

83+
restoreParams() {
84+
if (this.urlSearchParams.has('page')) {
85+
this.page = new Number(this.urlSearchParams.get('page'));
86+
}
87+
88+
if (this.urlSearchParams.has('status')) {
89+
this.status = this.urlSearchParams.get('status');
90+
}
91+
92+
if (this.urlSearchParams.has('date')) {
93+
this.status = this.urlSearchParams.get('date');
94+
}
95+
}
7496

97+
/**
98+
* Load webhook request logs.
99+
*
100+
* @param {Object} [params={}]
101+
* @param {Object} [options={}]
102+
* @memberof WebhookAttemptsComponent
103+
*/
75104
@task *getWebhookRequestLogs(params = {}, options = {}) {
105+
params = filterParams({ ...params, created_at: this.date, status: this.attemptStatus, page: this.page });
106+
76107
try {
77-
this.webhookRequestLogs = yield this.store.query('webhook-request-log', { limit: -1, sort: '-created_at', webhook_uuid: this.webhook.id, ...params }, options);
108+
this.webhookRequestLogs = yield this.store.query('webhook-request-log', { limit: 12, sort: '-created_at', webhook_uuid: this.webhook.id, page: this.page, ...params }, options);
78109
} catch (error) {
79110
this.notifications.serverError(error);
80111
}
81112
}
82113

114+
/**
115+
* Filter webhook attempt logs by date.
116+
*
117+
* @param {Object} { formattedDate }
118+
* @memberof WebhookAttemptsComponent
119+
*/
120+
@action filterByDate({ formattedDate }) {
121+
this.date = formattedDate;
122+
this.urlSearchParams.addParamToCurrentUrl('date', formattedDate);
123+
this.getWebhookRequestLogs.perform();
124+
}
125+
126+
/**
127+
* Clear date filter.
128+
*
129+
* @memberof WebhookAttemptsComponent
130+
*/
131+
@action clearDate() {
132+
this.date = null;
133+
this.urlSearchParams.removeParamFromCurrentUrl('date');
134+
this.getWebhookRequestLogs.perform();
135+
}
136+
137+
/**
138+
* Handle page change.
139+
*
140+
* @param {number} [page=1]
141+
* @memberof WebhookAttemptsComponent
142+
* @void
143+
*/
144+
@action changePage(page = 1) {
145+
this.page = page;
146+
this.urlSearchParams.addParamToCurrentUrl('page', page);
147+
this.getWebhookRequestLogs.perform();
148+
}
149+
83150
/**
84151
* @void
85152
*/
@@ -102,10 +169,12 @@ export default class WebhookAttemptsComponent extends Component {
102169
status = typeof status === 'string' ? status : null;
103170

104171
this.attemptStatus = status;
105-
106-
if (status) {
107-
this.loadWebhookRequestLogs({ status });
172+
if (status === null) {
173+
this.urlSearchParams.removeParamFromCurrentUrl('status');
174+
} else {
175+
this.urlSearchParams.addParamToCurrentUrl('status', status);
108176
}
177+
this.getWebhookRequestLogs.perform();
109178
}
110179

111180
/**

addon/styles/dev-engine.css

Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
1+
.webhook-attempts-pagination.fleetbase-pagination,
2+
.webhook-attempts-pagination {
3+
padding-top: 0;
4+
justify-content: end;
5+
}
6+
7+
.webhook-attempts-pagination > .fleetbase-pagination-meta-info-wrapper {
8+
flex: none;
9+
}
10+
11+
.webhook-attempts-date-filter-container {
12+
display: flex;
13+
flex-direction: row;
14+
align-items: center;
15+
position: relative;
16+
font-size: 0.875rem;
17+
line-height: 1.25rem;
18+
padding: 0.25rem 0.75rem;
19+
}
20+
21+
.webhook-attempts-date-filter-container > .date-picker-container input.fleetbase-date-picker {
22+
width: 100%;
23+
flex: 1;
24+
padding: 0;
25+
box-shadow: 0;
26+
background-color: transparent;
27+
font-size: 0.875rem;
28+
line-height: 1.25rem;
29+
border: 0;
30+
outline: 0;
31+
}
32+
33+
.webhook-attempts-date-filter-container > .date-picker-container input.fleetbase-date-picker:focus {
34+
box-shadow: none;
35+
border: 0;
36+
outline: 0;
37+
}
38+
39+
.webhook-attempts-date-filter-container > .date-filter-label {
40+
margin-right: 0.25rem;
41+
color: #000;
42+
}
43+
44+
body[data-theme='dark'] .webhook-attempts-date-filter-container > .date-filter-label {
45+
color: #9ca3af;
46+
}

0 commit comments

Comments
 (0)