Check-in [c9cd128c2c]
Not logged in
Overview

SHA1 Hash:c9cd128c2c2749739e6423fd668a5682395f7e76
Date: 2008-11-02 18:22:30
User: drh
Comment:Add submenu entries on timeline pages for selecting options such as "tickets only" and "200 entries per page" and so forth.
Timelines: ancestors | descendants | both | trunk
Other Links: files | ZIP archive | manifest

Tags And Properties
Changes
[hide diffs]

Modified src/timeline.c from [08490786af] to [16b352a347].

@@ -213,10 +213,24 @@
   ;
   return zBaseSql;
 }
 
 /*
+** Generate a submenu element with a single parameter change.
+*/
+static void timeline_submenu(
+  HQuery *pUrl,            /* Base URL */
+  const char *zMenuName,   /* Submenu name */
+  const char *zParam,      /* Parameter value to add or change */
+  const char *zValue,      /* Value of the new parameter */
+  const char *zRemove      /* Parameter to omit */
+){
+  style_submenu_element(zMenuName, zMenuName, "%s",
+                        url_render(pUrl, zParam, zValue, zRemove, 0));
+}
+
+/*
 ** WEBPAGE: timeline
 **
 ** Query parameters:
 **
 **    a=TIMESTAMP    after this date
@@ -223,11 +237,11 @@
 **    b=TIMESTAMP    before this date.
 **    n=COUNT        number of events in output
 **    p=RID          artifact RID and up to COUNT parents and ancestors
 **    d=RID          artifact RID and up to COUNT descendants
 **    u=USER         only if belonging to this user
-**    y=TYPE         'ci', 'w', 'tkt'
+**    y=TYPE         'ci', 'w', 't'
 **
 ** p= and d= can appear individually or together.  If either p= or d=
 ** appear, then u=, y=, a=, and b= are ignored.
 **
 ** If a= and b= appear, only a= is used.  If neither appear, the most
@@ -241,13 +255,14 @@
   Blob desc;                         /* Description of the timeline */
   int nEntry = atoi(PD("n","20"));   /* Max number of entries on timeline */
   int p_rid = atoi(PD("p","0"));     /* artifact p and its parents */
   int d_rid = atoi(PD("d","0"));     /* artifact d and its descendants */
   const char *zUser = P("u");        /* All entries by this user if not NULL */
-  const char *zType = P("y");        /* Type of events.  All if NULL */
+  const char *zType = PD("y","all"); /* Type of events.  All if NULL */
   const char *zAfter = P("a");       /* Events after this time */
   const char *zBefore = P("b");      /* Events before this time */
+  HQuery url;                        /* URL for various branch links */
 
   /* To view the timeline, must have permission to read project data.
   */
   login_check_credentials();
   if( !g.okRead ){ login_needed(); return; }
@@ -297,18 +312,18 @@
       blob_appendf(&desc, " of [%.10s]", zUuid);
     }
     db_prepare(&q, "SELECT * FROM timeline ORDER BY timestamp DESC");
   }else{
     int n;
-    Blob url;
     const char *zEType = "event";
-    const char *zDate;
-    blob_zero(&url);
-    blob_appendf(&url, "%s/timeline?n=%d", g.zBaseURL, nEntry);
-    if( zType ){
+    char *zDate;
+    char *zNEntry = mprintf("%d", nEntry);
+    url_initialize(&url, "timeline");
+    url_add_parameter(&url, "n", zNEntry);
+    if( zType[0]!='a' ){
       blob_appendf(&sql, " AND event.type=%Q", zType);
-      blob_appendf(&url, "&y=%T", zType);
+      url_add_parameter(&url, "y", zType);
       if( zType[0]=='c' ){
         zEType = "checkin";
       }else if( zType[0]=='w' ){
         zEType = "wiki edit";
       }else if( zType[0]=='t' ){
@@ -315,18 +330,19 @@
         zEType = "ticket change";
       }
     }
     if( zUser ){
       blob_appendf(&sql, " AND event.user=%Q", zUser);
-      blob_appendf(&url, "&u=%T", zUser);
+      url_add_parameter(&url, "u", zUser);
     }
     if( zAfter ){
       while( isspace(zAfter[0]) ){ zAfter++; }
       if( zAfter[0] ){
         blob_appendf(&sql,
            " AND event.mtime>=(SELECT julianday(%Q, 'utc'))"
            " ORDER BY event.mtime ASC", zAfter);
+        url_add_parameter(&url, "a", zAfter);
         zBefore = 0;
       }else{
         zAfter = 0;
       }
     }else if( zBefore ){
@@ -333,10 +349,11 @@
       while( isspace(zBefore[0]) ){ zBefore++; }
       if( zBefore[0] ){
         blob_appendf(&sql,
            " AND event.mtime<=(SELECT julianday(%Q, 'utc'))"
            " ORDER BY event.mtime DESC", zBefore);
+        url_add_parameter(&url, "b", zBefore);
        }else{
         zBefore = 0;
       }
     }else{
       blob_appendf(&sql, " ORDER BY event.mtime DESC");
@@ -343,10 +360,13 @@
     }
     blob_appendf(&sql, " LIMIT %d", nEntry);
     db_multi_exec("%s", blob_str(&sql));
 
     n = db_int(0, "SELECT count(*) FROM timeline");
+    if( n<nEntry && zAfter ){
+      cgi_redirect(url_render(&url, "a", 0, "b", 0));
+    }
     if( zAfter==0 && zBefore==0 ){
       blob_appendf(&desc, "%d most recent %ss", n, zEType);
     }else{
       blob_appendf(&desc, "%d %ss", n, zEType);
     }
@@ -359,15 +379,36 @@
       blob_appendf(&desc, " occurring on or before %h.<br>", zBefore);
     }
     if( g.okHistory ){
       if( zAfter || n==nEntry ){
         zDate = db_text(0, "SELECT min(timestamp) FROM timeline");
-        blob_appendf(&desc, " <a href='%b&b=%s'>[older]</a>", &url, zDate);
+        timeline_submenu(&url, "Older", "b", zDate, "a");
+        free(zDate);
       }
       if( zBefore || (zAfter && n==nEntry) ){
         zDate = db_text(0, "SELECT max(timestamp) FROM timeline");
-        blob_appendf(&desc, " <a href='%b&a=%s'>[more recent]</a>", &url,zDate);
+        timeline_submenu(&url, "Newer", "a", zDate, "b");
+        free(zDate);
+      }else{
+        if( zType[0]!='a' ){
+          timeline_submenu(&url, "All Types", "y", "all", 0);
+        }
+        if( zType[0]!='w' ){
+          timeline_submenu(&url, "Wiki Only", "y", "w", 0);
+        }
+        if( zType[0]!='c' ){
+          timeline_submenu(&url, "Checkins Only", "y", "ci", 0);
+        }
+        if( zType[0]!='t' ){
+          timeline_submenu(&url, "Tickets Only", "y", "t", 0);
+        }
+      }
+      if( nEntry>20 ){
+        timeline_submenu(&url, "20 Events", "n", "20", 0);
+      }
+      if( nEntry<200 ){
+        timeline_submenu(&url, "200 Events", "n", "200", 0);
       }
     }
   }
   blob_zero(&sql);
   db_prepare(&q, "SELECT * FROM timeline ORDER BY timestamp DESC");

Modified src/url.c from [ab868aa832] to [8b85115038].

@@ -172,6 +172,78 @@
     if( zMsg ) printf("%s%s\n", zMsg, zProxy);
     url_parse(zProxy);
     g.urlPath = zOriginalUrl;
     g.urlHostname = zOriginalHost;
   }
+}
+
+#if INTERFACE
+/*
+** An instance of this object is used to build a URL with query parameters.
+*/
+struct HQuery {
+  Blob url;                  /* The URL */
+  const char *zBase;         /* The base URL */
+  int nParam;                /* Number of parameters.  Max 10 */
+  const char *azName[10];    /* Parameter names */
+  const char *azValue[10];   /* Parameter values */
+};
+#endif
+
+/*
+** Initialize the URL object.
+*/
+void url_initialize(HQuery *p, const char *zBase){
+  blob_zero(&p->url);
+  p->zBase = zBase;
+  p->nParam = 0;
+}
+
+/*
+** Add a fixed parameter to an HQuery.
+*/
+void url_add_parameter(HQuery *p, const char *zName, const char *zValue){
+  assert( p->nParam < count(p->azName) );
+  assert( p->nParam < count(p->azValue) );
+  p->azName[p->nParam] = zName;
+  p->azValue[p->nParam] = zValue;
+  p->nParam++;
+}
+
+/*
+** Render the URL with a parameter override.
+*/
+char *url_render(
+  HQuery *p,              /* Base URL */
+  const char *zName1,     /* First override */
+  const char *zValue1,    /* First override value */
+  const char *zName2,     /* Second override */
+  const char *zValue2     /* Second override value */
+){
+  const char *zSep = "?";
+  int i;
+
+  blob_reset(&p->url);
+  blob_appendf(&p->url, "%s/%s", g.zBaseURL, p->zBase);
+  for(i=0; i<p->nParam; i++){
+    const char *z = p->azValue[i];
+    if( zName1 && strcmp(zName1,p->azName[i])==0 ){
+      zName1 = 0;
+      z = zValue1;
+      if( z==0 ) continue;
+    }
+    if( zName2 && strcmp(zName2,p->azName[i])==0 ){
+      zName2 = 0;
+      z = zValue2;
+      if( z==0 ) continue;
+    }
+    blob_appendf(&p->url, "%s%s=%T", zSep, p->azName[i], z);
+    zSep = "&";
+  }
+  if( zName1 && zValue1 ){
+    blob_appendf(&p->url, "%s%s=%T", zSep, zName1, zValue1);
+  }
+  if( zName2 && zValue2 ){
+    blob_appendf(&p->url, "%s%s=%T", zSep, zName2, zValue2);
+  }
+  return blob_str(&p->url);
 }