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