Skip to content

Commit 125c91b

Browse files
committed
implement some suggestions
1 parent 4de389e commit 125c91b

File tree

9 files changed

+489
-175
lines changed

9 files changed

+489
-175
lines changed

backend/actions/Task/getTaskOverview.js

Lines changed: 6 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
'use strict';
22

33
const Archetype = require('archetype');
4+
const escape = require('regexp.escape');
45

56
const GetTaskOverviewParams = new Archetype({
67
start: { $type: Date },
@@ -12,29 +13,13 @@ const GetTaskOverviewParams = new Archetype({
1213
/** Statuses shown on the Task overview page. */
1314
const OVERVIEW_STATUSES = ['pending', 'succeeded', 'failed', 'cancelled'];
1415

15-
function ensureDate(value) {
16-
if (value == null) return value;
17-
if (value instanceof Date) return value;
18-
if (typeof value === 'string' || typeof value === 'number') {
19-
const d = new Date(value);
20-
if (!Number.isNaN(d.getTime())) return d;
21-
}
22-
return value;
23-
}
24-
25-
function escapeRegex(str) {
26-
return String(str).replace(/[.*+?^${}()|[\]\\]/g, '\\$&');
27-
}
28-
2916
function buildMatch(params) {
3017
const { start, end, status, name } = params;
3118
const match = {};
32-
const startDate = ensureDate(start);
33-
const endDate = ensureDate(end);
34-
if (startDate != null && endDate != null) {
35-
match.scheduledAt = { $gte: startDate, $lt: endDate };
36-
} else if (startDate != null) {
37-
match.scheduledAt = { $gte: startDate };
19+
if (start != null && end != null) {
20+
match.scheduledAt = { $gte: start, $lt: end };
21+
} else if (start != null) {
22+
match.scheduledAt = { $gte: start };
3823
}
3924
const statusVal = typeof status === 'string' ? status.trim() : status;
4025
if (statusVal != null && statusVal !== '') {
@@ -44,15 +29,13 @@ function buildMatch(params) {
4429
}
4530
if (name != null && name !== '') {
4631
const nameStr = typeof name === 'string' ? name.trim() : String(name);
47-
match.name = { $regex: escapeRegex(nameStr), $options: 'i' };
32+
match.name = { $regex: escape(nameStr), $options: 'i' };
4833
}
4934
return match;
5035
}
5136

5237
module.exports = ({ db }) => async function getTaskOverview(params) {
5338
params = new GetTaskOverviewParams(params);
54-
params.start = ensureDate(params.start);
55-
params.end = ensureDate(params.end);
5639
if (typeof params.status === 'string') params.status = params.status.trim();
5740
if (typeof params.name === 'string') params.name = params.name.trim();
5841
const { Task } = db.models;

backend/actions/Task/getTasks.js

Lines changed: 2 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
'use strict';
22

33
const Archetype = require('archetype');
4+
const escape = require('regexp.escape');
45

56
const GetTasksParams = new Archetype({
67
start: { $type: Date },
@@ -16,11 +17,6 @@ const ALL_STATUSES = ['pending', 'in_progress', 'succeeded', 'failed', 'cancelle
1617
/** Max documents per request to avoid excessive memory and response size. */
1718
const MAX_LIMIT = 2000;
1819

19-
/** Escape special regex characters so the name is matched literally. */
20-
function escapeRegex(str) {
21-
return String(str).replace(/[.*+?^${}()|[\]\\]/g, '\\$&');
22-
}
23-
2420
function buildMatch(params) {
2521
const { start, end, status, name } = params;
2622
const match = {};
@@ -37,7 +33,7 @@ function buildMatch(params) {
3733
}
3834
if (name != null && name !== '') {
3935
const nameStr = typeof name === 'string' ? name.trim() : String(name);
40-
match.name = { $regex: escapeRegex(nameStr), $options: 'i' };
36+
match.name = { $regex: escape(nameStr), $options: 'i' };
4137
}
4238
return match;
4339
}
@@ -56,20 +52,8 @@ const TASK_PROJECT_STAGE = {
5652
parameters: '$payload'
5753
};
5854

59-
function ensureDate(value) {
60-
if (value == null) return value;
61-
if (value instanceof Date) return value;
62-
if (typeof value === 'string' || typeof value === 'number') {
63-
const d = new Date(value);
64-
if (!Number.isNaN(d.getTime())) return d;
65-
}
66-
return value;
67-
}
68-
6955
module.exports = ({ db }) => async function getTasks(params) {
7056
params = new GetTasksParams(params);
71-
params.start = ensureDate(params.start);
72-
params.end = ensureDate(params.end);
7357
if (typeof params.status === 'string') params.status = params.status.trim();
7458
if (typeof params.name === 'string') params.name = params.name.trim();
7559

frontend/src/_util/dateRange.js

Lines changed: 82 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,82 @@
1+
'use strict';
2+
3+
const DATE_FILTERS = [
4+
{ value: 'last_hour', label: 'Last Hour' },
5+
{ value: 'today', label: 'Today' },
6+
{ value: 'yesterday', label: 'Yesterday' },
7+
{ value: 'thisWeek', label: 'This Week' },
8+
{ value: 'lastWeek', label: 'Last Week' },
9+
{ value: 'thisMonth', label: 'This Month' },
10+
{ value: 'lastMonth', label: 'Last Month' }
11+
];
12+
13+
const DATE_FILTER_VALUES = DATE_FILTERS.map(f => f.value);
14+
15+
/**
16+
* Returns { start, end } Date objects for a given range key (e.g. 'last_hour', 'today').
17+
* Month ranges use UTC boundaries.
18+
* @param {string} selectedRange - One of DATE_FILTER_VALUES
19+
* @returns {{ start: Date, end: Date }}
20+
*/
21+
function getDateRangeForRange(selectedRange) {
22+
const now = new Date();
23+
let start, end;
24+
switch (selectedRange) {
25+
case 'last_hour':
26+
start = new Date();
27+
start.setHours(start.getHours() - 1);
28+
end = new Date();
29+
break;
30+
case 'today':
31+
start = new Date();
32+
start.setHours(0, 0, 0, 0);
33+
end = new Date();
34+
end.setHours(23, 59, 59, 999);
35+
break;
36+
case 'yesterday':
37+
start = new Date(now);
38+
start.setDate(start.getDate() - 1);
39+
start.setHours(0, 0, 0, 0);
40+
end = new Date(start);
41+
end.setHours(23, 59, 59, 999);
42+
break;
43+
case 'thisWeek':
44+
start = new Date(now.getTime() - (7 * 86400000));
45+
start.setHours(0, 0, 0, 0);
46+
end = new Date();
47+
end.setHours(23, 59, 59, 999);
48+
break;
49+
case 'lastWeek':
50+
start = new Date(now.getTime() - (14 * 86400000));
51+
start.setHours(0, 0, 0, 0);
52+
end = new Date(now.getTime() - (7 * 86400000));
53+
end.setHours(23, 59, 59, 999);
54+
break;
55+
case 'thisMonth': {
56+
const y = now.getUTCFullYear();
57+
const m = now.getUTCMonth();
58+
start = new Date(Date.UTC(y, m, 1, 0, 0, 0, 0));
59+
end = new Date(Date.UTC(y, m + 1, 0, 23, 59, 59, 999));
60+
break;
61+
}
62+
case 'lastMonth': {
63+
const y = now.getUTCFullYear();
64+
const m = now.getUTCMonth();
65+
start = new Date(Date.UTC(y, m - 1, 1, 0, 0, 0, 0));
66+
end = new Date(Date.UTC(y, m, 0, 23, 59, 59, 999));
67+
break;
68+
}
69+
default:
70+
start = new Date();
71+
start.setHours(start.getHours() - 1);
72+
end = new Date();
73+
break;
74+
}
75+
return { start, end };
76+
}
77+
78+
module.exports = {
79+
DATE_FILTERS,
80+
DATE_FILTER_VALUES,
81+
getDateRangeForRange
82+
};

frontend/src/task-by-name/task-by-name.html

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -44,7 +44,7 @@
4444
<div class="flex items-center gap-2">
4545
<label class="text-sm font-medium text-gray-700">Per page</label>
4646
<select
47-
v-model="pageSize"
47+
v-model.number="pageSize"
4848
@change="onPageSizeChange"
4949
class="border border-gray-300 rounded-md shadow-sm px-3 py-2 text-sm text-gray-700 bg-white hover:border-gray-400 focus:outline-none focus:ring-2 focus:ring-ultramarine-500 focus:border-ultramarine-500"
5050
>

frontend/src/task-by-name/task-by-name.js

Lines changed: 1 addition & 68 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
// Page: all tasks with a given name. Reuses task-details to render the list (many tasks).
44
const template = require('./task-by-name.html');
55
const api = require('../api');
6+
const { DATE_FILTERS, DATE_FILTER_VALUES, getDateRangeForRange } = require('../_util/dateRange');
67

78
function buildTaskGroup(name, tasks) {
89
const statusCounts = { pending: 0, succeeded: 0, failed: 0, cancelled: 0, in_progress: 0, unknown: 0 };
@@ -28,74 +29,6 @@ function buildTaskGroup(name, tasks) {
2829

2930
const PAGE_SIZE_OPTIONS = [25, 50, 100, 200];
3031

31-
const DATE_FILTERS = [
32-
{ value: 'last_hour', label: 'Last Hour' },
33-
{ value: 'today', label: 'Today' },
34-
{ value: 'yesterday', label: 'Yesterday' },
35-
{ value: 'thisWeek', label: 'This Week' },
36-
{ value: 'lastWeek', label: 'Last Week' },
37-
{ value: 'thisMonth', label: 'This Month' },
38-
{ value: 'lastMonth', label: 'Last Month' }
39-
];
40-
const DATE_FILTER_VALUES = DATE_FILTERS.map(f => f.value);
41-
42-
function getDateRangeForRange(selectedRange) {
43-
const now = new Date();
44-
let start, end;
45-
switch (selectedRange) {
46-
case 'last_hour':
47-
start = new Date();
48-
start.setHours(start.getHours() - 1);
49-
end = new Date();
50-
break;
51-
case 'today':
52-
start = new Date();
53-
start.setHours(0, 0, 0, 0);
54-
end = new Date();
55-
end.setHours(23, 59, 59, 999);
56-
break;
57-
case 'yesterday':
58-
start = new Date(now);
59-
start.setDate(start.getDate() - 1);
60-
start.setHours(0, 0, 0, 0);
61-
end = new Date(start);
62-
end.setHours(23, 59, 59, 999);
63-
break;
64-
case 'thisWeek':
65-
start = new Date(now.getTime() - (7 * 86400000));
66-
start.setHours(0, 0, 0, 0);
67-
end = new Date();
68-
end.setHours(23, 59, 59, 999);
69-
break;
70-
case 'lastWeek':
71-
start = new Date(now.getTime() - (14 * 86400000));
72-
start.setHours(0, 0, 0, 0);
73-
end = new Date(now.getTime() - (7 * 86400000));
74-
end.setHours(23, 59, 59, 999);
75-
break;
76-
case 'thisMonth': {
77-
const y = now.getUTCFullYear();
78-
const m = now.getUTCMonth();
79-
start = new Date(Date.UTC(y, m, 1, 0, 0, 0, 0));
80-
end = new Date(Date.UTC(y, m + 1, 0, 23, 59, 59, 999));
81-
break;
82-
}
83-
case 'lastMonth': {
84-
const y = now.getUTCFullYear();
85-
const m = now.getUTCMonth();
86-
start = new Date(Date.UTC(y, m - 1, 1, 0, 0, 0, 0));
87-
end = new Date(Date.UTC(y, m, 0, 23, 59, 59, 999));
88-
break;
89-
}
90-
default:
91-
start = new Date();
92-
start.setHours(start.getHours() - 1);
93-
end = new Date();
94-
break;
95-
}
96-
return { start, end };
97-
}
98-
9932
module.exports = app => app.component('task-by-name', {
10033
template,
10134
data: () => ({

frontend/src/tasks/tasks.js

Lines changed: 3 additions & 65 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22

33
const template = require('./tasks.html');
44
const api = require('../api');
5+
const { DATE_FILTERS, getDateRangeForRange } = require('../_util/dateRange');
56

67
module.exports = app => app.component('tasks', {
78
data: () => ({
@@ -11,15 +12,7 @@ module.exports = app => app.component('tasks', {
1112
selectedRange: 'last_hour',
1213
start: null,
1314
end: null,
14-
dateFilters: [
15-
{ value: 'last_hour', label: 'Last Hour' },
16-
{ value: 'today', label: 'Today' },
17-
{ value: 'yesterday', label: 'Yesterday' },
18-
{ value: 'thisWeek', label: 'This Week' },
19-
{ value: 'lastWeek', label: 'Last Week' },
20-
{ value: 'thisMonth', label: 'This Month' },
21-
{ value: 'lastMonth', label: 'Last Month' }
22-
],
15+
dateFilters: DATE_FILTERS,
2316
selectedStatus: 'all',
2417
statusFilters: [
2518
{ label: 'All', value: 'all' },
@@ -234,64 +227,9 @@ module.exports = app => app.component('tasks', {
234227
}, 300);
235228
},
236229
async updateDateRange() {
237-
const now = new Date();
238-
let start, end;
239-
240-
switch (this.selectedRange) {
241-
case 'last_hour':
242-
start = new Date();
243-
start.setHours(start.getHours() - 1);
244-
end = new Date();
245-
break;
246-
case 'today':
247-
start = new Date();
248-
start.setHours(0, 0, 0, 0);
249-
end = new Date();
250-
end.setHours(23, 59, 59, 999);
251-
break;
252-
case 'yesterday':
253-
start = new Date(now);
254-
start.setDate(start.getDate() - 1);
255-
start.setHours(0, 0, 0, 0);
256-
end = new Date(start);
257-
end.setHours(23, 59, 59, 999);
258-
break;
259-
case 'thisWeek':
260-
start = new Date(now.getTime() - (7 * 86400000));
261-
start.setHours(0, 0, 0, 0);
262-
end = new Date();
263-
end.setHours(23, 59, 59, 999);
264-
break;
265-
case 'lastWeek':
266-
start = new Date(now.getTime() - (14 * 86400000));
267-
start.setHours(0, 0, 0, 0);
268-
end = new Date(now.getTime() - (7 * 86400000));
269-
end.setHours(23, 59, 59, 999);
270-
break;
271-
case 'thisMonth': {
272-
const y = now.getUTCFullYear();
273-
const m = now.getUTCMonth();
274-
start = new Date(Date.UTC(y, m, 1, 0, 0, 0, 0));
275-
end = new Date(Date.UTC(y, m + 1, 0, 23, 59, 59, 999));
276-
break;
277-
}
278-
case 'lastMonth': {
279-
const y = now.getUTCFullYear();
280-
const m = now.getUTCMonth();
281-
start = new Date(Date.UTC(y, m - 1, 1, 0, 0, 0, 0));
282-
end = new Date(Date.UTC(y, m, 0, 23, 59, 59, 999));
283-
break;
284-
}
285-
default:
286-
start = new Date();
287-
start.setHours(start.getHours() - 1);
288-
end = new Date();
289-
break;
290-
}
291-
230+
const { start, end } = getDateRangeForRange(this.selectedRange);
292231
this.start = start;
293232
this.end = end;
294-
295233
await this.getTasks();
296234
}
297235
},

package.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@
1919
"extrovert": "^0.2.0",
2020
"marked": "15.0.12",
2121
"node-inspect-extracted": "3.x",
22+
"regexp.escape": "^2.0.1",
2223
"tailwindcss": "3.4.0",
2324
"vue": "3.x",
2425
"vue-toastification": "^2.0.0-rc.5",

0 commit comments

Comments
 (0)