Fossil SCM

Add the "circa" capability to the timeline. Check-in hyperlinks go to the "diff" page by default, rather than the "detail" page.

drh 2009-08-15 16:47 trunk
Commit 5a539f82dc57e0a6794def3d1cbc367c71668efd
2 files changed +24 -8 +34 -2
+24 -8
--- src/info.c
+++ src/info.c
@@ -425,11 +425,11 @@
425425
}
426426
db_finalize(&q);
427427
@ </td></tr>
428428
@ <tr><th>Commands:</th>
429429
@ <td>
430
- @ <a href="%s(g.zBaseURL)/vdiff/%d(rid)">diff</a>
430
+ @ <a href="%s(g.zBaseURL)/vdiff/%s(zShortUuid)">diff</a>
431431
@ | <a href="%s(g.zBaseURL)/dir?ci=%s(zShortUuid)">files</a>
432432
@ | <a href="%s(g.zBaseURL)/zip/%s(zProjName)-%s(zShortUuid).zip?uuid=%s(zUuid)">
433433
@ ZIP archive</a>
434434
@ | <a href="%s(g.zBaseURL)/artifact/%d(rid)">manifest</a>
435435
if( g.okWrite ){
@@ -671,10 +671,11 @@
671671
@ %h(blob_str(&out))
672672
blob_reset(&from);
673673
blob_reset(&to);
674674
blob_reset(&out);
675675
}
676
+
676677
677678
/*
678679
** WEBPAGE: vdiff
679680
** URL: /vdiff?name=RID
680681
**
@@ -685,29 +686,44 @@
685686
Stmt q;
686687
char *zUuid;
687688
688689
login_check_credentials();
689690
if( !g.okRead ){ login_needed(); return; }
690
- style_header("Check-in Changes");
691691
login_anonymous_available();
692692
693693
rid = name_to_rid(PD("name",""));
694694
if( rid==0 ){
695695
fossil_redirect_home();
696696
}
697
+ zUuid = db_text(0, "SELECT uuid FROM blob WHERE rid=%d", rid);
698
+ style_header("Check-in [%.10s]", zUuid);
699
+ db_prepare(&q,
700
+ "SELECT datetime(mtime), "
701
+ " coalesce(event.ecomment,event.comment),"
702
+ " coalesce(event.euser,event.user)"
703
+ " FROM event WHERE type='ci' AND objid=%d",
704
+ rid
705
+ );
706
+ while( db_step(&q)==SQLITE_ROW ){
707
+ const char *zDate = db_column_text(&q, 0);
708
+ const char *zUser = db_column_text(&q, 2);
709
+ const char *zComment = db_column_text(&q, 1);
710
+ @ <h2>Check-in %s(zUuid)</h2>
711
+ @ <p>Made by %h(zUser) on
712
+ link_to_date(zDate, ":");
713
+ @ %w(zComment). <a href="%s(g.zBaseURL)/ci/%s(zUuid)">[details]</a></p>
714
+ @ <hr>
715
+ }
716
+ db_finalize(&q);
697717
db_prepare(&q,
698718
"SELECT pid, fid, name"
699719
" FROM mlink, filename"
700720
" WHERE mlink.mid=%d"
701721
" AND filename.fnid=mlink.fnid"
702722
" ORDER BY name",
703723
rid
704724
);
705
- zUuid = db_text(0, "SELECT uuid FROM blob WHERE rid=%d", rid);
706
- @ <h2>All Changes In Check-in
707
- hyperlink_to_uuid(zUuid);
708
- @ </h2>
709725
while( db_step(&q)==SQLITE_ROW ){
710726
int pid = db_column_int(&q,0);
711727
int fid = db_column_int(&q,1);
712728
const char *zName = db_column_text(&q,2);
713729
@ <p><a href="%s(g.zBaseURL)/finfo?name=%T(zName)">%h(zName)</a></p>
@@ -716,11 +732,10 @@
716732
@ </pre></blockquote>
717733
}
718734
db_finalize(&q);
719735
style_footer();
720736
}
721
-
722737
723738
/*
724739
** Write a description of an object to the www reply.
725740
**
726741
** If the object is a file then mention:
@@ -851,10 +866,11 @@
851866
}
852867
}else if( linkToView ){
853868
@ <a href="%s(g.zBaseURL)/artifact/%d(rid)">[view]</a>
854869
}
855870
}
871
+
856872
857873
/*
858874
** WEBPAGE: fdiff
859875
**
860876
** Two arguments, v1 and v2, are integers. Show the difference between
@@ -1192,11 +1208,11 @@
11921208
@ <p>No such object: %h(zName)</p>
11931209
style_footer();
11941210
return;
11951211
}
11961212
if( db_exists("SELECT 1 FROM mlink WHERE mid=%d", rid) ){
1197
- ci_page();
1213
+ vdiff_page();
11981214
}else
11991215
if( db_exists("SELECT 1 FROM tagxref JOIN tag USING(tagid)"
12001216
" WHERE rid=%d AND tagname LIKE 'wiki-%%'", rid) ){
12011217
winfo_page();
12021218
}else
12031219
--- src/info.c
+++ src/info.c
@@ -425,11 +425,11 @@
425 }
426 db_finalize(&q);
427 @ </td></tr>
428 @ <tr><th>Commands:</th>
429 @ <td>
430 @ <a href="%s(g.zBaseURL)/vdiff/%d(rid)">diff</a>
431 @ | <a href="%s(g.zBaseURL)/dir?ci=%s(zShortUuid)">files</a>
432 @ | <a href="%s(g.zBaseURL)/zip/%s(zProjName)-%s(zShortUuid).zip?uuid=%s(zUuid)">
433 @ ZIP archive</a>
434 @ | <a href="%s(g.zBaseURL)/artifact/%d(rid)">manifest</a>
435 if( g.okWrite ){
@@ -671,10 +671,11 @@
671 @ %h(blob_str(&out))
672 blob_reset(&from);
673 blob_reset(&to);
674 blob_reset(&out);
675 }
 
676
677 /*
678 ** WEBPAGE: vdiff
679 ** URL: /vdiff?name=RID
680 **
@@ -685,29 +686,44 @@
685 Stmt q;
686 char *zUuid;
687
688 login_check_credentials();
689 if( !g.okRead ){ login_needed(); return; }
690 style_header("Check-in Changes");
691 login_anonymous_available();
692
693 rid = name_to_rid(PD("name",""));
694 if( rid==0 ){
695 fossil_redirect_home();
696 }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
697 db_prepare(&q,
698 "SELECT pid, fid, name"
699 " FROM mlink, filename"
700 " WHERE mlink.mid=%d"
701 " AND filename.fnid=mlink.fnid"
702 " ORDER BY name",
703 rid
704 );
705 zUuid = db_text(0, "SELECT uuid FROM blob WHERE rid=%d", rid);
706 @ <h2>All Changes In Check-in
707 hyperlink_to_uuid(zUuid);
708 @ </h2>
709 while( db_step(&q)==SQLITE_ROW ){
710 int pid = db_column_int(&q,0);
711 int fid = db_column_int(&q,1);
712 const char *zName = db_column_text(&q,2);
713 @ <p><a href="%s(g.zBaseURL)/finfo?name=%T(zName)">%h(zName)</a></p>
@@ -716,11 +732,10 @@
716 @ </pre></blockquote>
717 }
718 db_finalize(&q);
719 style_footer();
720 }
721
722
723 /*
724 ** Write a description of an object to the www reply.
725 **
726 ** If the object is a file then mention:
@@ -851,10 +866,11 @@
851 }
852 }else if( linkToView ){
853 @ <a href="%s(g.zBaseURL)/artifact/%d(rid)">[view]</a>
854 }
855 }
 
856
857 /*
858 ** WEBPAGE: fdiff
859 **
860 ** Two arguments, v1 and v2, are integers. Show the difference between
@@ -1192,11 +1208,11 @@
1192 @ <p>No such object: %h(zName)</p>
1193 style_footer();
1194 return;
1195 }
1196 if( db_exists("SELECT 1 FROM mlink WHERE mid=%d", rid) ){
1197 ci_page();
1198 }else
1199 if( db_exists("SELECT 1 FROM tagxref JOIN tag USING(tagid)"
1200 " WHERE rid=%d AND tagname LIKE 'wiki-%%'", rid) ){
1201 winfo_page();
1202 }else
1203
--- src/info.c
+++ src/info.c
@@ -425,11 +425,11 @@
425 }
426 db_finalize(&q);
427 @ </td></tr>
428 @ <tr><th>Commands:</th>
429 @ <td>
430 @ <a href="%s(g.zBaseURL)/vdiff/%s(zShortUuid)">diff</a>
431 @ | <a href="%s(g.zBaseURL)/dir?ci=%s(zShortUuid)">files</a>
432 @ | <a href="%s(g.zBaseURL)/zip/%s(zProjName)-%s(zShortUuid).zip?uuid=%s(zUuid)">
433 @ ZIP archive</a>
434 @ | <a href="%s(g.zBaseURL)/artifact/%d(rid)">manifest</a>
435 if( g.okWrite ){
@@ -671,10 +671,11 @@
671 @ %h(blob_str(&out))
672 blob_reset(&from);
673 blob_reset(&to);
674 blob_reset(&out);
675 }
676
677
678 /*
679 ** WEBPAGE: vdiff
680 ** URL: /vdiff?name=RID
681 **
@@ -685,29 +686,44 @@
686 Stmt q;
687 char *zUuid;
688
689 login_check_credentials();
690 if( !g.okRead ){ login_needed(); return; }
 
691 login_anonymous_available();
692
693 rid = name_to_rid(PD("name",""));
694 if( rid==0 ){
695 fossil_redirect_home();
696 }
697 zUuid = db_text(0, "SELECT uuid FROM blob WHERE rid=%d", rid);
698 style_header("Check-in [%.10s]", zUuid);
699 db_prepare(&q,
700 "SELECT datetime(mtime), "
701 " coalesce(event.ecomment,event.comment),"
702 " coalesce(event.euser,event.user)"
703 " FROM event WHERE type='ci' AND objid=%d",
704 rid
705 );
706 while( db_step(&q)==SQLITE_ROW ){
707 const char *zDate = db_column_text(&q, 0);
708 const char *zUser = db_column_text(&q, 2);
709 const char *zComment = db_column_text(&q, 1);
710 @ <h2>Check-in %s(zUuid)</h2>
711 @ <p>Made by %h(zUser) on
712 link_to_date(zDate, ":");
713 @ %w(zComment). <a href="%s(g.zBaseURL)/ci/%s(zUuid)">[details]</a></p>
714 @ <hr>
715 }
716 db_finalize(&q);
717 db_prepare(&q,
718 "SELECT pid, fid, name"
719 " FROM mlink, filename"
720 " WHERE mlink.mid=%d"
721 " AND filename.fnid=mlink.fnid"
722 " ORDER BY name",
723 rid
724 );
 
 
 
 
725 while( db_step(&q)==SQLITE_ROW ){
726 int pid = db_column_int(&q,0);
727 int fid = db_column_int(&q,1);
728 const char *zName = db_column_text(&q,2);
729 @ <p><a href="%s(g.zBaseURL)/finfo?name=%T(zName)">%h(zName)</a></p>
@@ -716,11 +732,10 @@
732 @ </pre></blockquote>
733 }
734 db_finalize(&q);
735 style_footer();
736 }
 
737
738 /*
739 ** Write a description of an object to the www reply.
740 **
741 ** If the object is a file then mention:
@@ -851,10 +866,11 @@
866 }
867 }else if( linkToView ){
868 @ <a href="%s(g.zBaseURL)/artifact/%d(rid)">[view]</a>
869 }
870 }
871
872
873 /*
874 ** WEBPAGE: fdiff
875 **
876 ** Two arguments, v1 and v2, are integers. Show the difference between
@@ -1192,11 +1208,11 @@
1208 @ <p>No such object: %h(zName)</p>
1209 style_footer();
1210 return;
1211 }
1212 if( db_exists("SELECT 1 FROM mlink WHERE mid=%d", rid) ){
1213 vdiff_page();
1214 }else
1215 if( db_exists("SELECT 1 FROM tagxref JOIN tag USING(tagid)"
1216 " WHERE rid=%d AND tagname LIKE 'wiki-%%'", rid) ){
1217 winfo_page();
1218 }else
1219
+34 -2
--- src/timeline.c
+++ src/timeline.c
@@ -54,11 +54,11 @@
5454
){
5555
char zShortUuid[UUID_SIZE+1];
5656
sprintf(zShortUuid, "%.10s", zUuid);
5757
if( g.okHistory ){
5858
@ <a onmouseover='%s(zIn)("m%d(id)")' onmouseout='%s(zOut)("m%d(id)")'
59
- @ href="%s(g.zBaseURL)/ci/%s(zUuid)">[%s(zShortUuid)]</a>
59
+ @ href="%s(g.zBaseURL)/vdiff/%s(zUuid)">[%s(zShortUuid)]</a>
6060
}else{
6161
@ <b onmouseover='%s(zIn)("m%d(id)")' onmouseout='%s(zOut)("m%d(id)")'>
6262
@ [%s(zShortUuid)]</b>
6363
}
6464
}
@@ -308,10 +308,11 @@
308308
**
309309
** Query parameters:
310310
**
311311
** a=TIMESTAMP after this date
312312
** b=TIMESTAMP before this date.
313
+** c=TIMESTAMP "circa" this date.
313314
** n=COUNT number of events in output
314315
** p=RID artifact RID and up to COUNT parents and ancestors
315316
** d=RID artifact RID and up to COUNT descendants
316317
** t=TAGID show only check-ins with the given tagid
317318
** u=USER only if belonging to this user
@@ -334,10 +335,11 @@
334335
int d_rid = atoi(PD("d","0")); /* artifact d and its descendants */
335336
const char *zUser = P("u"); /* All entries by this user if not NULL */
336337
const char *zType = PD("y","all"); /* Type of events. All if NULL */
337338
const char *zAfter = P("a"); /* Events after this time */
338339
const char *zBefore = P("b"); /* Events before this time */
340
+ const char *zCirca = P("c"); /* Events near this time */
339341
const char *zTagName = P("t"); /* Show events with this tag */
340342
HQuery url; /* URL for various branch links */
341343
int tagid; /* Tag ID */
342344
343345
/* To view the timeline, must have permission to read project data.
@@ -442,10 +444,31 @@
442444
" ORDER BY event.mtime DESC", zBefore);
443445
url_add_parameter(&url, "b", zBefore);
444446
}else{
445447
zBefore = 0;
446448
}
449
+ }else if( zCirca ){
450
+ while( isspace(zCirca[0]) ){ zCirca++; }
451
+ if( zCirca[0] ){
452
+ double rCirca = db_double(0.0, "SELECT julianday(%Q, 'utc')", zCirca);
453
+ Blob sql2;
454
+ blob_init(&sql2, blob_str(&sql), -1);
455
+ blob_appendf(&sql2,
456
+ " AND event.mtime<=%f ORDER BY event.mtime DESC LIMIT %d",
457
+ rCirca, (nEntry+1)/2
458
+ );
459
+ db_multi_exec("%s", blob_str(&sql2));
460
+ blob_reset(&sql2);
461
+ blob_appendf(&sql,
462
+ " AND event.mtime>=%f ORDER BY event.mtime ASC",
463
+ rCirca
464
+ );
465
+ nEntry -= (nEntry+1)/2;
466
+ url_add_parameter(&url, "c", zCirca);
467
+ }else{
468
+ zCirca = 0;
469
+ }
447470
}else{
448471
blob_appendf(&sql, " ORDER BY event.mtime DESC");
449472
}
450473
blob_appendf(&sql, " LIMIT %d", nEntry);
451474
db_multi_exec("%s", blob_str(&sql));
@@ -452,11 +475,11 @@
452475
453476
n = db_int(0, "SELECT count(*) FROM timeline");
454477
if( n<nEntry && zAfter ){
455478
cgi_redirect(url_render(&url, "a", 0, "b", 0));
456479
}
457
- if( zAfter==0 && zBefore==0 ){
480
+ if( zAfter==0 && zBefore==0 && zCirca==0 ){
458481
blob_appendf(&desc, "%d most recent %ss", n, zEType);
459482
}else{
460483
blob_appendf(&desc, "%d %ss", n, zEType);
461484
}
462485
if( zUser ){
@@ -467,10 +490,12 @@
467490
}
468491
if( zAfter ){
469492
blob_appendf(&desc, " occurring on or after %h.<br>", zAfter);
470493
}else if( zBefore ){
471494
blob_appendf(&desc, " occurring on or before %h.<br>", zBefore);
495
+ }else if( zCirca ){
496
+ blob_appendf(&desc, " occurring around %h.<br>", zCirca);
472497
}
473498
if( g.okHistory ){
474499
if( zAfter || n==nEntry ){
475500
zDate = db_text(0, "SELECT min(timestamp) FROM timeline");
476501
timeline_submenu(&url, "Older", "b", zDate, "a");
@@ -601,10 +626,17 @@
601626
@ }
602627
@ }
603628
@ </script>
604629
style_footer();
605630
}
631
+
632
+/*
633
+** Render the date string given as a hyperlink to a "circa" timeline.
634
+*/
635
+void link_to_date(const char *zDate, const char *zSuffix){
636
+ @ <a href="%s(g.zBaseURL)/timeline?c=%t(zDate)">%h(zDate)</a>%s(zSuffix)
637
+}
606638
607639
/*
608640
** The input query q selects various records. Print a human-readable
609641
** summary of those records.
610642
**
611643
--- src/timeline.c
+++ src/timeline.c
@@ -54,11 +54,11 @@
54 ){
55 char zShortUuid[UUID_SIZE+1];
56 sprintf(zShortUuid, "%.10s", zUuid);
57 if( g.okHistory ){
58 @ <a onmouseover='%s(zIn)("m%d(id)")' onmouseout='%s(zOut)("m%d(id)")'
59 @ href="%s(g.zBaseURL)/ci/%s(zUuid)">[%s(zShortUuid)]</a>
60 }else{
61 @ <b onmouseover='%s(zIn)("m%d(id)")' onmouseout='%s(zOut)("m%d(id)")'>
62 @ [%s(zShortUuid)]</b>
63 }
64 }
@@ -308,10 +308,11 @@
308 **
309 ** Query parameters:
310 **
311 ** a=TIMESTAMP after this date
312 ** b=TIMESTAMP before this date.
 
313 ** n=COUNT number of events in output
314 ** p=RID artifact RID and up to COUNT parents and ancestors
315 ** d=RID artifact RID and up to COUNT descendants
316 ** t=TAGID show only check-ins with the given tagid
317 ** u=USER only if belonging to this user
@@ -334,10 +335,11 @@
334 int d_rid = atoi(PD("d","0")); /* artifact d and its descendants */
335 const char *zUser = P("u"); /* All entries by this user if not NULL */
336 const char *zType = PD("y","all"); /* Type of events. All if NULL */
337 const char *zAfter = P("a"); /* Events after this time */
338 const char *zBefore = P("b"); /* Events before this time */
 
339 const char *zTagName = P("t"); /* Show events with this tag */
340 HQuery url; /* URL for various branch links */
341 int tagid; /* Tag ID */
342
343 /* To view the timeline, must have permission to read project data.
@@ -442,10 +444,31 @@
442 " ORDER BY event.mtime DESC", zBefore);
443 url_add_parameter(&url, "b", zBefore);
444 }else{
445 zBefore = 0;
446 }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
447 }else{
448 blob_appendf(&sql, " ORDER BY event.mtime DESC");
449 }
450 blob_appendf(&sql, " LIMIT %d", nEntry);
451 db_multi_exec("%s", blob_str(&sql));
@@ -452,11 +475,11 @@
452
453 n = db_int(0, "SELECT count(*) FROM timeline");
454 if( n<nEntry && zAfter ){
455 cgi_redirect(url_render(&url, "a", 0, "b", 0));
456 }
457 if( zAfter==0 && zBefore==0 ){
458 blob_appendf(&desc, "%d most recent %ss", n, zEType);
459 }else{
460 blob_appendf(&desc, "%d %ss", n, zEType);
461 }
462 if( zUser ){
@@ -467,10 +490,12 @@
467 }
468 if( zAfter ){
469 blob_appendf(&desc, " occurring on or after %h.<br>", zAfter);
470 }else if( zBefore ){
471 blob_appendf(&desc, " occurring on or before %h.<br>", zBefore);
 
 
472 }
473 if( g.okHistory ){
474 if( zAfter || n==nEntry ){
475 zDate = db_text(0, "SELECT min(timestamp) FROM timeline");
476 timeline_submenu(&url, "Older", "b", zDate, "a");
@@ -601,10 +626,17 @@
601 @ }
602 @ }
603 @ </script>
604 style_footer();
605 }
 
 
 
 
 
 
 
606
607 /*
608 ** The input query q selects various records. Print a human-readable
609 ** summary of those records.
610 **
611
--- src/timeline.c
+++ src/timeline.c
@@ -54,11 +54,11 @@
54 ){
55 char zShortUuid[UUID_SIZE+1];
56 sprintf(zShortUuid, "%.10s", zUuid);
57 if( g.okHistory ){
58 @ <a onmouseover='%s(zIn)("m%d(id)")' onmouseout='%s(zOut)("m%d(id)")'
59 @ href="%s(g.zBaseURL)/vdiff/%s(zUuid)">[%s(zShortUuid)]</a>
60 }else{
61 @ <b onmouseover='%s(zIn)("m%d(id)")' onmouseout='%s(zOut)("m%d(id)")'>
62 @ [%s(zShortUuid)]</b>
63 }
64 }
@@ -308,10 +308,11 @@
308 **
309 ** Query parameters:
310 **
311 ** a=TIMESTAMP after this date
312 ** b=TIMESTAMP before this date.
313 ** c=TIMESTAMP "circa" this date.
314 ** n=COUNT number of events in output
315 ** p=RID artifact RID and up to COUNT parents and ancestors
316 ** d=RID artifact RID and up to COUNT descendants
317 ** t=TAGID show only check-ins with the given tagid
318 ** u=USER only if belonging to this user
@@ -334,10 +335,11 @@
335 int d_rid = atoi(PD("d","0")); /* artifact d and its descendants */
336 const char *zUser = P("u"); /* All entries by this user if not NULL */
337 const char *zType = PD("y","all"); /* Type of events. All if NULL */
338 const char *zAfter = P("a"); /* Events after this time */
339 const char *zBefore = P("b"); /* Events before this time */
340 const char *zCirca = P("c"); /* Events near this time */
341 const char *zTagName = P("t"); /* Show events with this tag */
342 HQuery url; /* URL for various branch links */
343 int tagid; /* Tag ID */
344
345 /* To view the timeline, must have permission to read project data.
@@ -442,10 +444,31 @@
444 " ORDER BY event.mtime DESC", zBefore);
445 url_add_parameter(&url, "b", zBefore);
446 }else{
447 zBefore = 0;
448 }
449 }else if( zCirca ){
450 while( isspace(zCirca[0]) ){ zCirca++; }
451 if( zCirca[0] ){
452 double rCirca = db_double(0.0, "SELECT julianday(%Q, 'utc')", zCirca);
453 Blob sql2;
454 blob_init(&sql2, blob_str(&sql), -1);
455 blob_appendf(&sql2,
456 " AND event.mtime<=%f ORDER BY event.mtime DESC LIMIT %d",
457 rCirca, (nEntry+1)/2
458 );
459 db_multi_exec("%s", blob_str(&sql2));
460 blob_reset(&sql2);
461 blob_appendf(&sql,
462 " AND event.mtime>=%f ORDER BY event.mtime ASC",
463 rCirca
464 );
465 nEntry -= (nEntry+1)/2;
466 url_add_parameter(&url, "c", zCirca);
467 }else{
468 zCirca = 0;
469 }
470 }else{
471 blob_appendf(&sql, " ORDER BY event.mtime DESC");
472 }
473 blob_appendf(&sql, " LIMIT %d", nEntry);
474 db_multi_exec("%s", blob_str(&sql));
@@ -452,11 +475,11 @@
475
476 n = db_int(0, "SELECT count(*) FROM timeline");
477 if( n<nEntry && zAfter ){
478 cgi_redirect(url_render(&url, "a", 0, "b", 0));
479 }
480 if( zAfter==0 && zBefore==0 && zCirca==0 ){
481 blob_appendf(&desc, "%d most recent %ss", n, zEType);
482 }else{
483 blob_appendf(&desc, "%d %ss", n, zEType);
484 }
485 if( zUser ){
@@ -467,10 +490,12 @@
490 }
491 if( zAfter ){
492 blob_appendf(&desc, " occurring on or after %h.<br>", zAfter);
493 }else if( zBefore ){
494 blob_appendf(&desc, " occurring on or before %h.<br>", zBefore);
495 }else if( zCirca ){
496 blob_appendf(&desc, " occurring around %h.<br>", zCirca);
497 }
498 if( g.okHistory ){
499 if( zAfter || n==nEntry ){
500 zDate = db_text(0, "SELECT min(timestamp) FROM timeline");
501 timeline_submenu(&url, "Older", "b", zDate, "a");
@@ -601,10 +626,17 @@
626 @ }
627 @ }
628 @ </script>
629 style_footer();
630 }
631
632 /*
633 ** Render the date string given as a hyperlink to a "circa" timeline.
634 */
635 void link_to_date(const char *zDate, const char *zSuffix){
636 @ <a href="%s(g.zBaseURL)/timeline?c=%t(zDate)">%h(zDate)</a>%s(zSuffix)
637 }
638
639 /*
640 ** The input query q selects various records. Print a human-readable
641 ** summary of those records.
642 **
643

Keyboard Shortcuts

Open search /
Next entry (timeline) j
Previous entry (timeline) k
Open focused entry Enter
Show this help ?
Toggle theme Top nav button