99
1010"use strict" ;
1111
12- const beginningOfTime = 1_262_304_000 ; // Jan 01 2010, 00:00 in seconds
13- const endOfTime = 2_147_483_647 ; // Jan 19, 2038, 03:14 in seconds
14- let from = beginningOfTime ;
15- let until = endOfTime ;
12+ // These values are provided by the API (/info/database).
13+ // We initialize them as null and populate them during page init.
14+ let beginningOfTime = null ; // seconds since epoch (set from API: info/database.earliest_timestamp)
15+ // endOfTime should be the end of today (local), in seconds since epoch
16+ const endOfTime = moment ( ) . endOf ( "day" ) . unix ( ) ;
17+ let from = null ;
18+ let until = null ;
1619
1720const dateformat = "MMM Do YYYY, HH:mm" ;
1821
@@ -40,7 +43,52 @@ function getDnssecConfig() {
4043 } ) ;
4144}
4245
46+ // Fetch database info (earliest timestamp, sizes, ...) from the API and
47+ // initialize related globals.
48+ function getDatabaseInfo ( ) {
49+ $ . getJSON ( document . body . dataset . apiurl + "/info/database" , data => {
50+ // earliest_timestamp is provided in seconds since epoch
51+ // We have two sources: earliest_timestamp_disk (on-disk) and earliest_timestamp (in-memory)
52+ // Use whichever is smallest and non-zero
53+ const diskTimestamp = Number ( data . earliest_timestamp_disk ) ;
54+ const memoryTimestamp = Number ( data . earliest_timestamp ) ;
55+
56+ // Filter out zero/invalid timestamps
57+ const validTimestamps = [ diskTimestamp , memoryTimestamp ] . filter ( ts => ts > 0 ) ;
58+
59+ // Use the smallest valid timestamp, or null if none exist
60+ beginningOfTime = validTimestamps . length > 0 ? Math . min ( ...validTimestamps ) : null ;
61+
62+ // Round down to nearest 5-minute segment (300 seconds) if valid
63+ if ( beginningOfTime !== null ) {
64+ beginningOfTime = Math . floor ( beginningOfTime / 300 ) * 300 ;
65+ }
66+
67+ // If from/until were not provided via GET, default them
68+ // Only use defaults if beginningOfTime is valid
69+ if ( beginningOfTime !== null ) {
70+ from ??= beginningOfTime ;
71+ until ??= endOfTime ;
72+ }
73+
74+ initDateRangePicker ( ) ;
75+ } ) ;
76+ }
77+
4378function initDateRangePicker ( ) {
79+ // If there's no valid data in the database, disable the datepicker
80+ if ( beginningOfTime === null ) {
81+ $ ( "#querytime" ) . prop ( "disabled" , true ) ;
82+ $ ( "#querytime" ) . addClass ( "disabled" ) ;
83+ $ ( "#querytime-note" ) . text ( "ℹ️ No data in the database" ) ;
84+ return ;
85+ }
86+
87+ const minDateMoment = moment . unix ( beginningOfTime ) ;
88+ const maxDateMoment = moment . unix ( endOfTime ) ;
89+ const earliestDateStr = minDateMoment . format ( dateformat ) ;
90+ $ ( "#querytime-note" ) . text ( `Earliest date: ${ earliestDateStr } ` ) ;
91+
4492 $ ( "#querytime" ) . daterangepicker (
4593 {
4694 timePicker : true ,
@@ -52,21 +100,24 @@ function initDateRangePicker() {
52100 ranges : {
53101 "Last 10 Minutes" : [ moment ( ) . subtract ( 10 , "minutes" ) , moment ( ) ] ,
54102 "Last Hour" : [ moment ( ) . subtract ( 1 , "hours" ) , moment ( ) ] ,
55- Today : [ moment ( ) . startOf ( "day" ) , moment ( ) . endOf ( "day" ) ] ,
103+ Today : [ moment ( ) . startOf ( "day" ) , maxDateMoment ] ,
56104 Yesterday : [
57105 moment ( ) . subtract ( 1 , "days" ) . startOf ( "day" ) ,
58106 moment ( ) . subtract ( 1 , "days" ) . endOf ( "day" ) ,
59107 ] ,
60- "Last 7 Days" : [ moment ( ) . subtract ( 6 , "days" ) , moment ( ) . endOf ( "day" ) ] ,
61- "Last 30 Days" : [ moment ( ) . subtract ( 29 , "days" ) , moment ( ) . endOf ( "day" ) ] ,
62- "This Month" : [ moment ( ) . startOf ( "month" ) , moment ( ) . endOf ( "month" ) ] ,
108+ "Last 7 Days" : [ moment ( ) . subtract ( 6 , "days" ) . startOf ( "day" ) , maxDateMoment ] ,
109+ "Last 30 Days" : [ moment ( ) . subtract ( 29 , "days" ) . startOf ( "day" ) , maxDateMoment ] ,
110+ "This Month" : [ moment ( ) . startOf ( "month" ) , maxDateMoment ] ,
63111 "Last Month" : [
64112 moment ( ) . subtract ( 1 , "month" ) . startOf ( "month" ) ,
65113 moment ( ) . subtract ( 1 , "month" ) . endOf ( "month" ) ,
66114 ] ,
67- "This Year" : [ moment ( ) . startOf ( "year" ) , moment ( ) . endOf ( "year" ) ] ,
68- "All Time" : [ moment ( beginningOfTime * 1000 ) , moment ( endOfTime * 1000 ) ] , // convert to milliseconds since epoch
115+ "This Year" : [ moment ( ) . startOf ( "year" ) , maxDateMoment ] ,
116+ "All Time" : [ minDateMoment , maxDateMoment ] ,
69117 } ,
118+ // Don't allow selecting dates outside the database range
119+ minDate : minDateMoment ,
120+ maxDate : maxDateMoment ,
70121 opens : "center" ,
71122 showDropdowns : true ,
72123 autoUpdateInput : true ,
@@ -510,14 +561,15 @@ $(() => {
510561 const apiURL = getAPIURL ( GETDict ) ;
511562
512563 if ( "from" in GETDict ) {
513- from = GETDict . from ;
564+ from = Number ( GETDict . from ) ;
514565 }
515566
516567 if ( "until" in GETDict ) {
517- until = GETDict . until ;
568+ until = Number ( GETDict . until ) ;
518569 }
519570
520- initDateRangePicker ( ) ;
571+ // Fetch earliest timestamp from API and initialize date picker / table
572+ getDatabaseInfo ( ) ;
521573
522574 table = $ ( "#all-queries" ) . DataTable ( {
523575 ajax : {
0 commit comments