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
- branch=trunk inherited from [a28c83647d]
- sym-trunk inherited from [a28c83647d]
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); }