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: */ afcdc7ec97 2007-08-01 drh: void www_print_timeline(Stmt *pQuery){ 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> dbda8d6ce9 2007-07-21 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; 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"); afcdc7ec97 2007-08-01 drh: db_prepare(&q, 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: " ORDER BY event.mtime DESC" afcdc7ec97 2007-08-01 drh: ); afcdc7ec97 2007-08-01 drh: www_print_timeline(&q); afcdc7ec97 2007-08-01 drh: db_finalize(&q); dbda8d6ce9 2007-07-21 drh: style_footer(); dbda8d6ce9 2007-07-21 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: }