Check-in [c8a78004ce]
Not logged in
Overview

SHA1 Hash:c8a78004ce272d700f44890e7ce715a38afeac04
Date: 2008-10-20 16:05:03
User: drh
Comment:Improvements in the display of ticket history.
Timelines: ancestors | descendants | both | trunk
Other Links: files | ZIP archive | manifest

Tags And Properties
Changes
[hide diffs]

Modified src/info.c from [e9965b6667] to [219a4e589a].

@@ -833,35 +833,21 @@
   blob_reset(&content);
   style_footer();
 }
 
 /*
-** Return TRUE if the given BLOB contains a newline character.
-*/
-static int contains_newline(Blob *p){
-  const char *z = blob_str(p);
-  while( *z ){
-    if( *z=='\n' ) return 1;
-    z++;
-  }
-  return 0;
-}
-
-/*
 ** WEBPAGE: tinfo
 ** URL: /tinfo?name=UUID
 **
 ** Show the details of a ticket change control artifact.
 */
 void tinfo_page(void){
   int rid;
   Blob content;
   char *zDate;
-  int i;
   const char *zUuid;
   char zTktName[20];
-  const char *z;
   Manifest m;
 
   login_check_credentials();
   if( !g.okRdTkt ){ login_needed(); return; }
   rid = name_to_rid(PD("name","0"));
@@ -894,29 +880,12 @@
   @ <a href="%s(g.zTop)/tkthistory/%s(m.zTicketUuid)">ticket history</a>
   @ </p>
   @
   @ <ol>
   free(zDate);
-  for(i=0; i<m.nField; i++){
-    Blob val;
-    z = m.aField[i].zName;
-    blob_set(&val, m.aField[i].zValue);
-    if( z[0]=='+' ){
-      @ <li><p>Appended to %h(&z[1]):</p><blockquote>
-      wiki_convert(&val, 0, 0);
-      @ </blockquote></li>
-    }else if( blob_size(&val)<=50 && contains_newline(&val) ){
-      @ <li><p>Change %h(z) to:</p><blockquote>
-      wiki_convert(&val, 0, 0);
-      @ </blockquote></li>
-    }else{
-      @ <li><p>Change %h(z) to "%h(blob_str(&val))"</p></li>
-    }
-    blob_reset(&val);
-  }
-  manifest_clear(&m);
-  @ </ol>
+  ticket_output_change_artifact(&m);
+  manifest_clear(&m);
   style_footer();
 }
 
 
 /*

Modified src/tkt.c from [e278b1f557] to [06773a209f].

@@ -323,12 +323,15 @@
   if( g.okWrTkt ){
     style_submenu_element("Edit", "Edit The Ticket", "%s/tktedit?name=%T",
         g.zTop, PD("name",""));
   }
   if( g.okHistory ){
+    const char *zUuid = PD("name","");
     style_submenu_element("History", "History Of This Ticket",
-        "%s/tkthistory/%T", g.zTop, PD("name",""));
+        "%s/tkthistory/%T", g.zTop, zUuid);
+    style_submenu_element("Timeline", "Timeline Of This Ticket",
+        "%s/tkttimeline/%T", g.zTop, zUuid);
   }
   style_header("View Ticket");
   ticket_init();
   initializeVariablesFromDb();
   zScript = ticket_viewpage_code();
@@ -580,26 +583,30 @@
   }
   return 0;
 }
 
 /*
-** WEBPAGE: tkthistory
-** URL: /tkthistory?name=TICKETUUID
+** WEBPAGE: tkttimeline
+** URL: /tkttimeline?name=TICKETUUID
 **
-** Show the complete change history for a single ticket
+** Show the change history for a single ticket in timeline format.
 */
-void tkthistory_page(void){
+void tkttimeline_page(void){
   Stmt q;
   char *zTitle;
   char *zSQL;
   const char *zUuid;
   int tagid;
 
   login_check_credentials();
   if( !g.okHistory || !g.okRdTkt ){ login_needed(); return; }
   zUuid = PD("name","");
-  zTitle = mprintf("History Of Ticket %h", zUuid);
+  style_submenu_element("History", "History",
+    "%s/tkthistory/%s", g.zTop, zUuid);
+  style_submenu_element("Status", "Status",
+    "%s/info/%s", g.zTop, zUuid);
+  zTitle = mprintf("Timeline Of Ticket %h", zUuid);
   style_header(zTitle);
   free(zTitle);
 
   tagid = db_int(0, "SELECT tagid FROM tag WHERE tagname GLOB 'tkt-%q*'",zUuid);
   if( tagid==0 ){
@@ -614,6 +621,107 @@
   db_prepare(&q, zSQL);
   free(zSQL);
   www_print_timeline(&q);
   db_finalize(&q);
   style_footer();
+}
+
+/*
+** WEBPAGE: tkthistory
+** URL: /tkthistory?name=TICKETUUID
+**
+** Show the complete change history for a single ticket
+*/
+void tkthistory_page(void){
+  Stmt q;
+  char *zTitle;
+  const char *zUuid;
+  int tagid;
+
+  login_check_credentials();
+  if( !g.okHistory || !g.okRdTkt ){ login_needed(); return; }
+  zUuid = PD("name","");
+  zTitle = mprintf("History Of Ticket %h", zUuid);
+  style_submenu_element("Status", "Status",
+    "%s/info/%s", g.zTop, zUuid);
+  style_submenu_element("Timeline", "Timeline",
+    "%s/tkttimeline?name=%s", g.zTop, zUuid);
+  style_header(zTitle);
+  free(zTitle);
+
+  tagid = db_int(0, "SELECT tagid FROM tag WHERE tagname GLOB 'tkt-%q*'",zUuid);
+  if( tagid==0 ){
+    @ No such ticket: %h(zUuid)
+    style_footer();
+    return;
+  }
+  db_prepare(&q,
+    "SELECT objid, uuid FROM event, blob"
+    " WHERE objid IN (SELECT rid FROM tagxref WHERE tagid=%d)"
+    "   AND blob.rid=event.objid"
+    " ORDER BY mtime DESC",
+    tagid
+  );
+  while( db_step(&q)==SQLITE_ROW ){
+    Blob content;
+    Manifest m;
+    int rid = db_column_int(&q, 0);
+    const char *zChngUuid = db_column_text(&q, 1);
+    content_get(rid, &content);
+    if( manifest_parse(&m, &content) && m.type==CFTYPE_TICKET ){
+      char *zDate = db_text(0, "SELECT datetime(%.12f)", m.rDate);
+      char zUuid[12];
+      memcpy(zUuid, zChngUuid, 10);
+      zUuid[10] = 0;
+      @
+      @ <p>%s(zDate)
+      @ [<a href="%s(g.zTop)/artifact/%T(zChngUuid)">%s(zUuid)</a>]</a>
+      @ by %h(m.zUser):</p>
+      @
+      free(zDate);
+      ticket_output_change_artifact(&m);
+    }
+    manifest_clear(&m);
+  }
+  db_finalize(&q);
+  style_footer();
+}
+
+/*
+** Return TRUE if the given BLOB contains a newline character.
+*/
+static int contains_newline(Blob *p){
+  const char *z = blob_str(p);
+  while( *z ){
+    if( *z=='\n' ) return 1;
+    z++;
+  }
+  return 0;
+}
+
+/*
+** The pTkt object is a ticket change artifact.  Output a detailed
+** description of this object.
+*/
+void ticket_output_change_artifact(Manifest *pTkt){
+  int i;
+  @ <ol>
+  for(i=0; i<pTkt->nField; i++){
+    Blob val;
+    const char *z;
+    z = pTkt->aField[i].zName;
+    blob_set(&val, pTkt->aField[i].zValue);
+    if( z[0]=='+' ){
+      @ <li>Appended to %h(&z[1]):<blockquote>
+      wiki_convert(&val, 0, 0);
+      @ </blockquote></li>
+    }else if( blob_size(&val)<=50 && contains_newline(&val) ){
+      @ <li>Change %h(z) to:<blockquote>
+      wiki_convert(&val, 0, 0);
+      @ </blockquote></li>
+    }else{
+      @ <li>Change %h(z) to "%h(blob_str(&val))"</li>
+    }
+    blob_reset(&val);
+  }
+  @ </ol>
 }