@@ -79,6 +96,10 @@ class Search extends React.Component {
this.search(e.target.value);
}
+ onDateRangeChanged = (e) => {
+ this.props.setParams({dateRange: e.target.value});
+ }
+
search = debounce((q) => {
this.props.setParams({q});
}, 500)
@@ -95,6 +116,7 @@ const mapStateToProps = state => {
return {
statusKey,
qTemp: state.job.qTemp,
+ dateRange: state.job.dateRange,
loading: state.status[statusKey].loading
};
};
diff --git a/frontend/src/pages/JobsPage/JobsPage.jsx b/frontend/src/pages/JobsPage/JobsPage.jsx
index 6a4a76c..004d40e 100644
--- a/frontend/src/pages/JobsPage/JobsPage.jsx
+++ b/frontend/src/pages/JobsPage/JobsPage.jsx
@@ -126,6 +126,7 @@ class JobsPage extends React.Component {
jobs: PropTypes.array.isRequired,
killJobs: PropTypes.func.isRequired,
q: PropTypes.string,
+ dateRange: PropTypes.string,
routing: PropTypes.object.isRequired,
selectedIds: PropTypes.array.isRequired,
setParams: PropTypes.func.isRequired,
@@ -153,6 +154,7 @@ class JobsPage extends React.Component {
componentDidUpdate(prevProps) {
if (this.props.q !== prevProps.q ||
+ this.props.dateRange !== prevProps.dateRange ||
this.props.sortColumn !== prevProps.sortColumn ||
this.props.sortDirection !== prevProps.sortDirection ||
this.props.page !== prevProps.page ||
@@ -315,6 +317,7 @@ class JobsPage extends React.Component {
...QUERY_PARAM_DEFAULTS,
...query,
qTemp: query.q || '',
+ dateRange: query.dateRange || '1d',
page: query.page ? parseInt(query.page) : 0,
selectedIds: query.selectedIds ? query.selectedIds.split(',') : [],
selectedQueue: !query.selectedQueue ? 'all' : query.selectedQueue,
@@ -343,6 +346,7 @@ class JobsPage extends React.Component {
const mapStateToProps = state => ({
q: state.job.q,
+ dateRange: state.job.dateRange,
jobs: state.job.jobs,
page: state.job.page,
height: state.layout.height,
diff --git a/frontend/src/stores/job.js b/frontend/src/stores/job.js
index 629dea1..cf99a0e 100644
--- a/frontend/src/stores/job.js
+++ b/frontend/src/stores/job.js
@@ -24,6 +24,7 @@ export const SET_PAGE = 'SET_PAGE';
export const SET_QUEUES = 'SET_QUEUES';
export const SET_SEARCH = 'SET_SEARCH';
export const SET_SEARCH_TEMP = 'SET_SEARCH_TEMP';
+export const SET_DATE_RANGE = 'SET_DATE_RANGE';
export const SET_SELECTED_IDS = 'SET_SELECTED_IDS';
export const SET_SELECTED_QUEUE = 'SET_SELECTED_QUEUE';
export const SET_SELECTED_STATUS = 'SET_SELECTED_STATUS';
@@ -117,6 +118,7 @@ export const QUERY_PARAM_DEFAULTS = {
graphType: 'area',
page: 0,
q: '',
+ dateRange: '1d',
selectedIds: [],
selectedQueue: '',
selectedStatus: '',
@@ -135,6 +137,7 @@ const initialState = {
logsById: {},
page: 0,
q: '',
+ dateRange: '1d',
qTemp: '',
queues: [],
selectedIds: [],
@@ -214,6 +217,13 @@ actions[SET_SEARCH] = (state, { payload }) => {
};
};
+actions[SET_DATE_RANGE] = (state, { payload }) => {
+ return {
+ ...state,
+ dateRange: payload
+ };
+};
+
actions[SET_SEARCH_TEMP] = (state, { payload }) => {
return {
...state,
@@ -331,6 +341,13 @@ export function setSearch(q) {
};
};
+export function setDateRange(dateRange) {
+ return {
+ type: SET_DATE_RANGE,
+ payload: dateRange
+ };
+};
+
export function setSearchTemp(qTemp) {
return {
type: SET_SEARCH_TEMP,
@@ -419,6 +436,9 @@ export function setParams(params) {
if (params.q !== undefined)
dispatch(setSearch(params.q));
+ if (params.dateRange !== undefined)
+ dispatch(setDateRange(params.dateRange));
+
if (params.qTemp !== undefined)
dispatch(setSearchTemp(params.qTemp));
@@ -515,6 +535,7 @@ export function fetchJobs() {
const params = {
page: state.job.page,
q: state.job.q,
+ dateRange: state.job.dateRange,
sortDirection: state.job.sortDirection,
sortColumn: state.job.sortColumn
};
diff --git a/handlers/handlers.go b/handlers/handlers.go
index 23b7c1f..dea4d15 100644
--- a/handlers/handlers.go
+++ b/handlers/handlers.go
@@ -48,6 +48,7 @@ func (s *Server) Find(c echo.Context) error {
c.QueryParams()
search := c.QueryParam("q")
+ dateRange := c.QueryParam("dateRange")
queuesStr := c.QueryParam("queue")
statusStr := c.QueryParam("status")
column := c.QueryParam("sortColumn")
@@ -69,13 +70,14 @@ func (s *Server) Find(c echo.Context) error {
}
foundJobs, err := s.Storage.Find(&jobs.Options{
- Search: search,
- Limit: defaultQueryLimit,
- Offset: page * defaultQueryLimit,
- Queues: queues,
- SortBy: column,
- SortAsc: sort,
- Status: status,
+ Search: search,
+ DateRange: dateRange,
+ Limit: defaultQueryLimit,
+ Offset: page * defaultQueryLimit,
+ Queues: queues,
+ SortBy: column,
+ SortAsc: sort,
+ Status: status,
})
if err != nil {
diff --git a/jobs/jobs.go b/jobs/jobs.go
index 3075bf7..6c2da58 100644
--- a/jobs/jobs.go
+++ b/jobs/jobs.go
@@ -99,21 +99,22 @@ type StatusSummary struct {
// Options is the query options for the Find method to use
type Options struct {
- Search string
- Limit int
- Offset int
- Queues []string
- SortBy string
- SortAsc bool
- Status []string
+ Search string
+ DateRange string
+ Limit int
+ Offset int
+ Queues []string
+ SortBy string
+ SortAsc bool
+ Status []string
}
type JobStatsOptions struct {
- Queues []string
- Status []string
- Interval int64
- Start int64
- End int64
+ Queues []string
+ Status []string
+ Interval int64
+ Start int64
+ End int64
}
type JobStats struct {
diff --git a/jobs/postgres_store.go b/jobs/postgres_store.go
index f755376..33863c6 100644
--- a/jobs/postgres_store.go
+++ b/jobs/postgres_store.go
@@ -101,7 +101,26 @@ func (pq *postgreSQLStore) Find(opts *Options) ([]*Job, error) {
args = append(args, opts.Limit)
args = append(args, opts.Offset)
- whereClausesScan = append(whereClausesScan, "last_updated > (now() - interval '30 days')")
+ var interval string
+ switch opts.DateRange {
+ case "10m":
+ interval = "10 minutes"
+ case "1h":
+ interval = "1 hour"
+ case "1d":
+ interval = "1 day"
+ case "2d":
+ interval = "2 days"
+ case "3d":
+ interval = "3 days"
+ case "7d":
+ interval = "7 days"
+ case "30d":
+ interval = "30 days"
+ default:
+ interval = "30 days"
+ }
+ whereClausesScan = append(whereClausesScan, fmt.Sprintf("last_updated > (now() - interval '%s')", interval))
// Split search into tokens (separated by whitespace). We will search for each token separately.
// If search is empty or only whitespace, tokens will be an empty array.