File Annotation
Not logged in
dbda8d6ce9 2007-07-21       drh: /*
dbda8d6ce9 2007-07-21       drh: ** Copyright (c) 2007 D. Richard Hipp
dbda8d6ce9 2007-07-21       drh: **
dbda8d6ce9 2007-07-21       drh: ** This program is free software; you can redistribute it and/or
dbda8d6ce9 2007-07-21       drh: ** modify it under the terms of the GNU General Public
dbda8d6ce9 2007-07-21       drh: ** License version 2 as published by the Free Software Foundation.
dbda8d6ce9 2007-07-21       drh: **
dbda8d6ce9 2007-07-21       drh: ** This program is distributed in the hope that it will be useful,
dbda8d6ce9 2007-07-21       drh: ** but WITHOUT ANY WARRANTY; without even the implied warranty of
dbda8d6ce9 2007-07-21       drh: ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
dbda8d6ce9 2007-07-21       drh: ** General Public License for more details.
dbda8d6ce9 2007-07-21       drh: **
dbda8d6ce9 2007-07-21       drh: ** You should have received a copy of the GNU General Public
dbda8d6ce9 2007-07-21       drh: ** License along with this library; if not, write to the
dbda8d6ce9 2007-07-21       drh: ** Free Software Foundation, Inc., 59 Temple Place - Suite 330,
dbda8d6ce9 2007-07-21       drh: ** Boston, MA  02111-1307, USA.
dbda8d6ce9 2007-07-21       drh: **
dbda8d6ce9 2007-07-21       drh: ** Author contact information:
dbda8d6ce9 2007-07-21       drh: **   drh@hwaci.com
dbda8d6ce9 2007-07-21       drh: **   http://www.hwaci.com/drh/
dbda8d6ce9 2007-07-21       drh: **
dbda8d6ce9 2007-07-21       drh: *******************************************************************************
dbda8d6ce9 2007-07-21       drh: **
dbda8d6ce9 2007-07-21       drh: ** This file contains code to implement the timeline web page
dbda8d6ce9 2007-07-21       drh: **
dbda8d6ce9 2007-07-21       drh: */
dbda8d6ce9 2007-07-21       drh: #include "config.h"
dbda8d6ce9 2007-07-21       drh: #include "timeline.h"
dbda8d6ce9 2007-07-21       drh: 
dbda8d6ce9 2007-07-21       drh: /*
dbda8d6ce9 2007-07-21       drh: ** Generate a hyperlink to a version.
dbda8d6ce9 2007-07-21       drh: */
dbda8d6ce9 2007-07-21       drh: void hyperlink_to_uuid(const char *zUuid){
dbda8d6ce9 2007-07-21       drh:   char zShortUuid[UUID_SIZE+1];
dbda8d6ce9 2007-07-21       drh:   sprintf(zShortUuid, "%.10s", zUuid);
fd36718ad9 2007-07-31       drh:   if( g.okHistory ){
fd36718ad9 2007-07-31       drh:     @ <a href="%s(g.zBaseURL)/vinfo/%s(zUuid)">[%s(zShortUuid)]</a>
fd36718ad9 2007-07-31       drh:   }else{
fd36718ad9 2007-07-31       drh:     @ <b>[%s(zShortUuid)]</b>
fd36718ad9 2007-07-31       drh:   }
dbda8d6ce9 2007-07-21       drh: }
dbda8d6ce9 2007-07-21       drh: 
dbda8d6ce9 2007-07-21       drh: /*
dbda8d6ce9 2007-07-21       drh: ** Generate a hyperlink to a diff between two versions.
dbda8d6ce9 2007-07-21       drh: */
dbda8d6ce9 2007-07-21       drh: void hyperlink_to_diff(const char *zV1, const char *zV2){
fd36718ad9 2007-07-31       drh:   if( g.okHistory ){
fd36718ad9 2007-07-31       drh:     if( zV2==0 ){
fd36718ad9 2007-07-31       drh:       @ <a href="%s(g.zBaseURL)/diff?v2=%s(zV1)">[diff]</a>
fd36718ad9 2007-07-31       drh:     }else{
fd36718ad9 2007-07-31       drh:       @ <a href="%s(g.zBaseURL)/diff?v1=%s(zV1)&v2=%s(zV2)">[diff]</a>
fd36718ad9 2007-07-31       drh:     }
dbda8d6ce9 2007-07-21       drh:   }
dbda8d6ce9 2007-07-21       drh: }
dbda8d6ce9 2007-07-21       drh: 
dbda8d6ce9 2007-07-21       drh: /*
afcdc7ec97 2007-08-01       drh: ** Output a timeline in the web format given a query.  The query
afcdc7ec97 2007-08-01       drh: ** should return 4 columns:
afcdc7ec97 2007-08-01       drh: **
afcdc7ec97 2007-08-01       drh: **    0.  UUID
afcdc7ec97 2007-08-01       drh: **    1.  Date/Time
afcdc7ec97 2007-08-01       drh: **    2.  Comment string
afcdc7ec97 2007-08-01       drh: **    3.  User
dbda8d6ce9 2007-07-21       drh: */
3945057916 2007-08-01       drh: void www_print_timeline(Stmt *pQuery, char *zLastDate){
afcdc7ec97 2007-08-01       drh:   char zPrevDate[20];
dbda8d6ce9 2007-07-21       drh:   zPrevDate[0] = 0;
dbda8d6ce9 2007-07-21       drh:   @ <table cellspacing=0 border=0 cellpadding=0>
afcdc7ec97 2007-08-01       drh:   while( db_step(pQuery)==SQLITE_ROW ){
afcdc7ec97 2007-08-01       drh:     const char *zDate = db_column_text(pQuery, 1);
dbda8d6ce9 2007-07-21       drh:     if( memcmp(zDate, zPrevDate, 10) ){
dbda8d6ce9 2007-07-21       drh:       sprintf(zPrevDate, "%.10s", zDate);
dbda8d6ce9 2007-07-21       drh:       @ <tr><td colspan=3>
dbda8d6ce9 2007-07-21       drh:       @ <table cellpadding=2 border=0>
dbda8d6ce9 2007-07-21       drh:       @ <tr><td bgcolor="#a0b5f4" class="border1">
dbda8d6ce9 2007-07-21       drh:       @ <table cellpadding=2 cellspacing=0 border=0><tr>
dbda8d6ce9 2007-07-21       drh:       @ <td bgcolor="#d0d9f4" class="bkgnd1">%s(zPrevDate)</td>
dbda8d6ce9 2007-07-21       drh:       @ </tr></table>
dbda8d6ce9 2007-07-21       drh:       @ </td></tr></table>
dbda8d6ce9 2007-07-21       drh:       @ </td></tr>
dbda8d6ce9 2007-07-21       drh:     }
dbda8d6ce9 2007-07-21       drh:     @ <tr><td valign="top">%s(&zDate[11])</td>
dbda8d6ce9 2007-07-21       drh:     @ <td width="20"></td>
dbda8d6ce9 2007-07-21       drh:     @ <td valign="top" align="left">
afcdc7ec97 2007-08-01       drh:     hyperlink_to_uuid(db_column_text(pQuery,0));
afcdc7ec97 2007-08-01       drh:     @ %h(db_column_text(pQuery,2)) (by %h(db_column_text(pQuery,3)))</td>
3945057916 2007-08-01       drh:     if( zLastDate ){
3945057916 2007-08-01       drh:       strcpy(zLastDate, zDate);
3945057916 2007-08-01       drh:     }
afcdc7ec97 2007-08-01       drh:   }
dbda8d6ce9 2007-07-21       drh:   @ </table>
afcdc7ec97 2007-08-01       drh: }
afcdc7ec97 2007-08-01       drh: 
afcdc7ec97 2007-08-01       drh: 
afcdc7ec97 2007-08-01       drh: 
afcdc7ec97 2007-08-01       drh: /*
afcdc7ec97 2007-08-01       drh: ** WEBPAGE: timeline
afcdc7ec97 2007-08-01       drh: */
afcdc7ec97 2007-08-01       drh: void page_timeline(void){
afcdc7ec97 2007-08-01       drh:   Stmt q;
3945057916 2007-08-01       drh:   char *zSQL;
3945057916 2007-08-01       drh:   char zDate[100];
3945057916 2007-08-01       drh:   const char *zStart = P("d");
3945057916 2007-08-01       drh:   int nEntry = atoi(PD("n","25"));
afcdc7ec97 2007-08-01       drh: 
afcdc7ec97 2007-08-01       drh:   /* To view the timeline, must have permission to read project data.
afcdc7ec97 2007-08-01       drh:   */
afcdc7ec97 2007-08-01       drh:   login_check_credentials();
afcdc7ec97 2007-08-01       drh:   if( !g.okRead ){ login_needed(); return; }
afcdc7ec97 2007-08-01       drh: 
afcdc7ec97 2007-08-01       drh:   style_header("Timeline");
3945057916 2007-08-01       drh:   if( !g.okHistory &&
3945057916 2007-08-01       drh:       db_exists("SELECT 1 FROM user"
3945057916 2007-08-01       drh:                 " WHERE login='anonymous'"
3945057916 2007-08-01       drh:                 "   AND cap LIKE '%%h%%'") ){
3945057916 2007-08-01       drh:     @ <p><b>Note:</b> You will be able to see much more timeline
3945057916 2007-08-01       drh:     @ information if <a href="%s(g.zBaseURL)/login">login</a>.</p>
3945057916 2007-08-01       drh:   }
3945057916 2007-08-01       drh:   zSQL = mprintf(
afcdc7ec97 2007-08-01       drh:     "SELECT uuid, datetime(event.mtime,'localtime'), comment, user"
afcdc7ec97 2007-08-01       drh:     "  FROM event, blob"
afcdc7ec97 2007-08-01       drh:     " WHERE event.type='ci' AND blob.rid=event.objid"
afcdc7ec97 2007-08-01       drh:   );
3945057916 2007-08-01       drh:   if( zStart ){
3945057916 2007-08-01       drh:     while( isspace(zStart[0]) ){ zStart++; }
3945057916 2007-08-01       drh:     if( zStart[0] ){
3945057916 2007-08-01       drh:       zSQL = mprintf("%z AND event.mtime<=julianday(%Q, 'localtime')",
3945057916 2007-08-01       drh:                       zSQL, zStart);
3945057916 2007-08-01       drh:     }
3945057916 2007-08-01       drh:   }
3945057916 2007-08-01       drh:   zSQL = mprintf("%z ORDER BY event.mtime DESC LIMIT %d", zSQL, nEntry);
3945057916 2007-08-01       drh:   db_prepare(&q, zSQL);
3945057916 2007-08-01       drh:   free(zSQL);
f5e8b1d736 2007-08-04       drh:   zDate[0] = 0;
3945057916 2007-08-01       drh:   www_print_timeline(&q, zDate);
afcdc7ec97 2007-08-01       drh:   db_finalize(&q);
3945057916 2007-08-01       drh:   if( zStart==0 ){
3945057916 2007-08-01       drh:     zStart = zDate;
3945057916 2007-08-01       drh:   }
3945057916 2007-08-01       drh:   @ <hr>
3945057916 2007-08-01       drh:   @ <form method="GET" action="%s(g.zBaseURL)/timeline">
3945057916 2007-08-01       drh:   @ Start Date:
3945057916 2007-08-01       drh:   @ <input type="text" size="30" value="%h(zStart)" name="d">
3945057916 2007-08-01       drh:   @ Number Of Entries:
3945057916 2007-08-01       drh:   @ <input type="text" size="4" value="%d(nEntry)" name="n">
3945057916 2007-08-01       drh:   @ <br><input type="submit" value="Submit">
3945057916 2007-08-01       drh:   @ </form>
3945057916 2007-08-01       drh:   @ <form method="GET" action="%s(g.zBaseURL)/timeline">
3945057916 2007-08-01       drh:   @ <input type="hidden" value="%h(zDate)" name="d">
3945057916 2007-08-01       drh:   @ <input type="hidden" value="%d(nEntry)" name="n">
3945057916 2007-08-01       drh:   @ <input type="submit" value="Next %d(nEntry) Rows">
3945057916 2007-08-01       drh:   @ </form>
dbda8d6ce9 2007-07-21       drh:   style_footer();
dbda8d6ce9 2007-07-21       drh: }
3945057916 2007-08-01       drh: 
dbda8d6ce9 2007-07-21       drh: /*
dbda8d6ce9 2007-07-21       drh: ** The input query q selects various records.  Print a human-readable
dbda8d6ce9 2007-07-21       drh: ** summary of those records.
dbda8d6ce9 2007-07-21       drh: **
dbda8d6ce9 2007-07-21       drh: ** Limit the number of entries printed to nLine.
dbda8d6ce9 2007-07-21       drh: */
dbda8d6ce9 2007-07-21       drh: void print_timeline(Stmt *q, int mxLine){
dbda8d6ce9 2007-07-21       drh:   int nLine = 0;
dbda8d6ce9 2007-07-21       drh:   char zPrevDate[20];
dbda8d6ce9 2007-07-21       drh:   zPrevDate[0] = 0;
dbda8d6ce9 2007-07-21       drh: 
dbda8d6ce9 2007-07-21       drh:   while( db_step(q)==SQLITE_ROW && nLine<=mxLine ){
dbda8d6ce9 2007-07-21       drh:     const char *zId = db_column_text(q, 0);
dbda8d6ce9 2007-07-21       drh:     const char *zDate = db_column_text(q, 1);
dbda8d6ce9 2007-07-21       drh:     const char *zCom = db_column_text(q, 2);
dbda8d6ce9 2007-07-21       drh:     char zUuid[UUID_SIZE+1];
dbda8d6ce9 2007-07-21       drh: 
dbda8d6ce9 2007-07-21       drh:     sprintf(zUuid, "%.10s", zId);
dbda8d6ce9 2007-07-21       drh:     if( memcmp(zDate, zPrevDate, 10) ){
dbda8d6ce9 2007-07-21       drh:       printf("=== %.10s ===\n", zDate);
dbda8d6ce9 2007-07-21       drh:       memcpy(zPrevDate, zDate, 10);
dbda8d6ce9 2007-07-21       drh:       nLine++;
dbda8d6ce9 2007-07-21       drh:     }
dbda8d6ce9 2007-07-21       drh:     if( zCom==0 ) zCom = "";
dbda8d6ce9 2007-07-21       drh:     printf("%.5s [%.10s] ", &zDate[11], zUuid);
dbda8d6ce9 2007-07-21       drh:     nLine += comment_print(zCom, 19, 79);
dbda8d6ce9 2007-07-21       drh:   }
dbda8d6ce9 2007-07-21       drh: }
dbda8d6ce9 2007-07-21       drh: 
dbda8d6ce9 2007-07-21       drh: 
dbda8d6ce9 2007-07-21       drh: /*
dbda8d6ce9 2007-07-21       drh: ** COMMAND: timeline
dbda8d6ce9 2007-07-21       drh: **
dbda8d6ce9 2007-07-21       drh: ** The timeline command works very much like the timeline webpage, but
dbda8d6ce9 2007-07-21       drh: ** shows much less data and has fewer configuration options.  It is
dbda8d6ce9 2007-07-21       drh: ** intended as a convenient shortcut for the common case of seeing
dbda8d6ce9 2007-07-21       drh: ** recent changes.
dbda8d6ce9 2007-07-21       drh: */
dbda8d6ce9 2007-07-21       drh: void timeline_cmd(void){
dbda8d6ce9 2007-07-21       drh:   Stmt q;
dbda8d6ce9 2007-07-21       drh:   db_must_be_within_tree();
dbda8d6ce9 2007-07-21       drh:   db_prepare(&q,
1a4dd313a8 2007-07-30       drh:     "SELECT uuid, datetime(event.mtime,'localtime'),"
1a4dd313a8 2007-07-30       drh:     "       comment || ' (by ' || user || ')'"
dbda8d6ce9 2007-07-21       drh:     "  FROM event, blob"
dbda8d6ce9 2007-07-21       drh:     " WHERE event.type='ci' AND blob.rid=event.objid"
dbda8d6ce9 2007-07-21       drh:     " ORDER BY event.mtime DESC"
dbda8d6ce9 2007-07-21       drh:   );
dbda8d6ce9 2007-07-21       drh:   print_timeline(&q, 20);
dbda8d6ce9 2007-07-21       drh:   db_finalize(&q);
dbda8d6ce9 2007-07-21       drh: }