Fossil SCM

Enhance the /brlist output to show a count of the number of check-ins on each branch, and to separate the "Status" and "Resolution" into separate columns, with the "Status" column being sortable. Enhance the SortableTable() javascript to always sort ASC on initial click and only go to DESC on a second click of the same column.

drh 2015-01-04 20:54 trunk
Commit 965905c884286e466c3494b3b15d10a1a902cd16
3 files changed +21 -18 +16 -9 +1
+21 -18
--- src/branch.c
+++ src/branch.c
@@ -307,25 +307,26 @@
307307
static char brlistQuery[] =
308308
@ SELECT
309309
@ tagxref.value,
310310
@ max(event.mtime),
311311
@ EXISTS(SELECT 1 FROM tagxref AS tx
312
-@ WHERE tx.rid=leaf.rid
312
+@ WHERE tx.rid=tagxref.rid
313313
@ AND tx.tagid=(SELECT tagid FROM tag WHERE tagname='closed')
314314
@ AND tx.tagtype>0),
315315
@ (SELECT tagxref.value
316316
@ FROM plink CROSS JOIN tagxref
317
-@ WHERE plink.pid=leaf.rid
317
+@ WHERE plink.pid=event.objid
318318
@ AND tagxref.rid=plink.cid
319319
@ AND tagxref.tagid=(SELECT tagid FROM tag WHERE tagname='branch')
320
-@ AND tagtype>0)
321
-@ FROM leaf, tagxref, tag, event
322
-@ WHERE leaf.rid=tagxref.rid
323
-@ AND tagxref.tagid=tag.tagid
320
+@ AND tagtype>0),
321
+@ count(*),
322
+@ (SELECT uuid FROM blob WHERE rid=tagxref.rid)
323
+@ FROM tagxref, tag, event
324
+@ WHERE tagxref.tagid=tag.tagid
324325
@ AND tagxref.tagtype>0
325326
@ AND tag.tagname='branch'
326
-@ AND event.objid=leaf.rid
327
+@ AND event.objid=tagxref.rid
327328
@ GROUP BY 1
328329
@ ORDER BY %d DESC;
329330
;
330331
331332
/*
@@ -350,39 +351,41 @@
350351
rNow = db_double(0.0, "SELECT julianday('now')");
351352
@ <div class="brlist"><table id="branchlisttable">
352353
@ <thead><tr>
353354
@ <th>Branch Name</th>
354355
@ <th>Age</th>
356
+ @ <th>Checkins</th>
355357
@ <th>Status</th>
358
+ @ <th>Resolution</th>
356359
@ </tr></thead><tbody>
357360
while( db_step(&q)==SQLITE_ROW ){
358361
const char *zBranch = db_column_text(&q, 0);
359362
double rMtime = db_column_double(&q, 1);
360363
int isClosed = db_column_int(&q, 2);
361364
const char *zMergeTo = db_column_text(&q, 3);
365
+ int nCkin = db_column_int(&q, 4);
366
+ const char *zLastCkin = db_column_text(&q, 5);
362367
char *zAge = human_readable_age(rNow - rMtime);
363368
sqlite3_int64 iMtime = (sqlite3_int64)(rMtime*86400.0);
364369
if( zMergeTo && zMergeTo[0]==0 ) zMergeTo = 0;
365370
@ <tr>
366
- @ <td>%z(href("%R/timeline?n=100&r=%T",zBranch))%h(zBranch)</a>
367
- @ <td data-sortkey="%016llx(iMtime)">%s(zAge)
371
+ @ <td>%z(href("%R/timeline?n=100&r=%T",zBranch))%h(zBranch)</a></td>
372
+ @ <td data-sortkey="%016llx(-iMtime)">%s(zAge)</td>
373
+ @ <td data-sortkey="%08x(-nCkin)">%d(nCkin)</td>
368374
fossil_free(zAge);
369
- if( isClosed && zMergeTo ){
370
- @ <td>closed,
371
- }else if( isClosed ){
372
- @ <td>closed
375
+ @ <td>%s(isClosed?"closed":"")</td>
376
+ if( zMergeTo ){
377
+ @ <td>merged into
378
+ @ %z(href("%R/timeline?f=%s",zLastCkin))%h(zMergeTo)</a></td>
373379
}else{
374
- @ <td>
375
- }
376
- if( zMergeTo ){
377
- @ merged into %z(href("%R/timeline?r=%T",zMergeTo))%h(zMergeTo)</a>
380
+ @ <td></td>
378381
}
379382
@ </tr>
380383
}
381384
@ </tbody></table></div>
382385
db_finalize(&q);
383
- output_table_sorting_javascript("branchlisttable","tkx");
386
+ output_table_sorting_javascript("branchlisttable","tkktx");
384387
style_footer();
385388
}
386389
387390
/*
388391
** WEBPAGE: brlist
389392
--- src/branch.c
+++ src/branch.c
@@ -307,25 +307,26 @@
307 static char brlistQuery[] =
308 @ SELECT
309 @ tagxref.value,
310 @ max(event.mtime),
311 @ EXISTS(SELECT 1 FROM tagxref AS tx
312 @ WHERE tx.rid=leaf.rid
313 @ AND tx.tagid=(SELECT tagid FROM tag WHERE tagname='closed')
314 @ AND tx.tagtype>0),
315 @ (SELECT tagxref.value
316 @ FROM plink CROSS JOIN tagxref
317 @ WHERE plink.pid=leaf.rid
318 @ AND tagxref.rid=plink.cid
319 @ AND tagxref.tagid=(SELECT tagid FROM tag WHERE tagname='branch')
320 @ AND tagtype>0)
321 @ FROM leaf, tagxref, tag, event
322 @ WHERE leaf.rid=tagxref.rid
323 @ AND tagxref.tagid=tag.tagid
 
324 @ AND tagxref.tagtype>0
325 @ AND tag.tagname='branch'
326 @ AND event.objid=leaf.rid
327 @ GROUP BY 1
328 @ ORDER BY %d DESC;
329 ;
330
331 /*
@@ -350,39 +351,41 @@
350 rNow = db_double(0.0, "SELECT julianday('now')");
351 @ <div class="brlist"><table id="branchlisttable">
352 @ <thead><tr>
353 @ <th>Branch Name</th>
354 @ <th>Age</th>
 
355 @ <th>Status</th>
 
356 @ </tr></thead><tbody>
357 while( db_step(&q)==SQLITE_ROW ){
358 const char *zBranch = db_column_text(&q, 0);
359 double rMtime = db_column_double(&q, 1);
360 int isClosed = db_column_int(&q, 2);
361 const char *zMergeTo = db_column_text(&q, 3);
 
 
362 char *zAge = human_readable_age(rNow - rMtime);
363 sqlite3_int64 iMtime = (sqlite3_int64)(rMtime*86400.0);
364 if( zMergeTo && zMergeTo[0]==0 ) zMergeTo = 0;
365 @ <tr>
366 @ <td>%z(href("%R/timeline?n=100&r=%T",zBranch))%h(zBranch)</a>
367 @ <td data-sortkey="%016llx(iMtime)">%s(zAge)
 
368 fossil_free(zAge);
369 if( isClosed && zMergeTo ){
370 @ <td>closed,
371 }else if( isClosed ){
372 @ <td>closed
373 }else{
374 @ <td>
375 }
376 if( zMergeTo ){
377 @ merged into %z(href("%R/timeline?r=%T",zMergeTo))%h(zMergeTo)</a>
378 }
379 @ </tr>
380 }
381 @ </tbody></table></div>
382 db_finalize(&q);
383 output_table_sorting_javascript("branchlisttable","tkx");
384 style_footer();
385 }
386
387 /*
388 ** WEBPAGE: brlist
389
--- src/branch.c
+++ src/branch.c
@@ -307,25 +307,26 @@
307 static char brlistQuery[] =
308 @ SELECT
309 @ tagxref.value,
310 @ max(event.mtime),
311 @ EXISTS(SELECT 1 FROM tagxref AS tx
312 @ WHERE tx.rid=tagxref.rid
313 @ AND tx.tagid=(SELECT tagid FROM tag WHERE tagname='closed')
314 @ AND tx.tagtype>0),
315 @ (SELECT tagxref.value
316 @ FROM plink CROSS JOIN tagxref
317 @ WHERE plink.pid=event.objid
318 @ AND tagxref.rid=plink.cid
319 @ AND tagxref.tagid=(SELECT tagid FROM tag WHERE tagname='branch')
320 @ AND tagtype>0),
321 @ count(*),
322 @ (SELECT uuid FROM blob WHERE rid=tagxref.rid)
323 @ FROM tagxref, tag, event
324 @ WHERE tagxref.tagid=tag.tagid
325 @ AND tagxref.tagtype>0
326 @ AND tag.tagname='branch'
327 @ AND event.objid=tagxref.rid
328 @ GROUP BY 1
329 @ ORDER BY %d DESC;
330 ;
331
332 /*
@@ -350,39 +351,41 @@
351 rNow = db_double(0.0, "SELECT julianday('now')");
352 @ <div class="brlist"><table id="branchlisttable">
353 @ <thead><tr>
354 @ <th>Branch Name</th>
355 @ <th>Age</th>
356 @ <th>Checkins</th>
357 @ <th>Status</th>
358 @ <th>Resolution</th>
359 @ </tr></thead><tbody>
360 while( db_step(&q)==SQLITE_ROW ){
361 const char *zBranch = db_column_text(&q, 0);
362 double rMtime = db_column_double(&q, 1);
363 int isClosed = db_column_int(&q, 2);
364 const char *zMergeTo = db_column_text(&q, 3);
365 int nCkin = db_column_int(&q, 4);
366 const char *zLastCkin = db_column_text(&q, 5);
367 char *zAge = human_readable_age(rNow - rMtime);
368 sqlite3_int64 iMtime = (sqlite3_int64)(rMtime*86400.0);
369 if( zMergeTo && zMergeTo[0]==0 ) zMergeTo = 0;
370 @ <tr>
371 @ <td>%z(href("%R/timeline?n=100&r=%T",zBranch))%h(zBranch)</a></td>
372 @ <td data-sortkey="%016llx(-iMtime)">%s(zAge)</td>
373 @ <td data-sortkey="%08x(-nCkin)">%d(nCkin)</td>
374 fossil_free(zAge);
375 @ <td>%s(isClosed?"closed":"")</td>
376 if( zMergeTo ){
377 @ <td>merged into
378 @ %z(href("%R/timeline?f=%s",zLastCkin))%h(zMergeTo)</a></td>
379 }else{
380 @ <td></td>
 
 
 
381 }
382 @ </tr>
383 }
384 @ </tbody></table></div>
385 db_finalize(&q);
386 output_table_sorting_javascript("branchlisttable","tkktx");
387 style_footer();
388 }
389
390 /*
391 ** WEBPAGE: brlist
392
+16 -9
--- src/report.c
+++ src/report.c
@@ -928,13 +928,20 @@
928928
**
929929
** http://www.webtoolkit.info/sortable-html-table.html
930930
**
931931
** This variation allows column types to be expressed using the second
932932
** argument. Each character of the second argument represent a column.
933
-** "t" means sort as text. "n" means sort numerically. "x" means do not
934
-** sort on this column. If there are fewer characters in zColumnTypes[] than
935
-** their are columns, the all extra columns assume type "t" (text).
933
+**
934
+** t Sort by text
935
+** n Sort numerically
936
+** k Sort by the data-sortkey property
937
+** x This column is not sortable
938
+**
939
+** If there are fewer characters in zColumnTypes[] than their are columns,
940
+** the all extra columns assume type "t" (text).
941
+**
942
+** Clicking on the same column header twice in a row inverts the sort.
936943
*/
937944
void output_table_sorting_javascript(const char *zTableId, const char *zColumnTypes){
938945
@ <script>
939946
@ function SortableTable(tableEl,columnTypes){
940947
@ this.tbody = tableEl.getElementsByTagName('tbody');
@@ -950,16 +957,15 @@
950957
@ this.sortIndex = column;
951958
@ var newRows = new Array();
952959
@ for (j = 0; j < this.tbody[0].rows.length; j++) {
953960
@ newRows[j] = this.tbody[0].rows[j];
954961
@ }
955
- @ newRows.sort(sortFn);
956
- @ if (cell.getAttribute("sortdir") == 'down') {
957
- @ newRows.reverse();
958
- @ cell.setAttribute('sortdir','up');
959
- @ } else {
960
- @ cell.setAttribute('sortdir','down');
962
+ @ if( this.sortIndex==this.prevColumn ){
963
+ @ newRows.reverse();
964
+ @ }else{
965
+ @ newRows.sort(sortFn);
966
+ @ this.prevColumn = this.sortIndex;
961967
@ }
962968
@ for (i=0;i<newRows.length;i++) {
963969
@ this.tbody[0].appendChild(newRows[i]);
964970
@ }
965971
@ }
@@ -986,10 +992,11 @@
986992
@ if(aa==bb) return 0;
987993
@ if(aa<bb) return -1;
988994
@ return 1;
989995
@ }
990996
@ var thisObject = this;
997
+ @ var prevColumn = -1;
991998
@ var x = tableEl.getElementsByTagName('thead');
992999
@ if(!(this.tbody && this.tbody[0].rows && this.tbody[0].rows.length>0)){
9931000
@ return;
9941001
@ }
9951002
@ if(x && x[0].rows && x[0].rows.length > 0) {
9961003
--- src/report.c
+++ src/report.c
@@ -928,13 +928,20 @@
928 **
929 ** http://www.webtoolkit.info/sortable-html-table.html
930 **
931 ** This variation allows column types to be expressed using the second
932 ** argument. Each character of the second argument represent a column.
933 ** "t" means sort as text. "n" means sort numerically. "x" means do not
934 ** sort on this column. If there are fewer characters in zColumnTypes[] than
935 ** their are columns, the all extra columns assume type "t" (text).
 
 
 
 
 
 
 
936 */
937 void output_table_sorting_javascript(const char *zTableId, const char *zColumnTypes){
938 @ <script>
939 @ function SortableTable(tableEl,columnTypes){
940 @ this.tbody = tableEl.getElementsByTagName('tbody');
@@ -950,16 +957,15 @@
950 @ this.sortIndex = column;
951 @ var newRows = new Array();
952 @ for (j = 0; j < this.tbody[0].rows.length; j++) {
953 @ newRows[j] = this.tbody[0].rows[j];
954 @ }
955 @ newRows.sort(sortFn);
956 @ if (cell.getAttribute("sortdir") == 'down') {
957 @ newRows.reverse();
958 @ cell.setAttribute('sortdir','up');
959 @ } else {
960 @ cell.setAttribute('sortdir','down');
961 @ }
962 @ for (i=0;i<newRows.length;i++) {
963 @ this.tbody[0].appendChild(newRows[i]);
964 @ }
965 @ }
@@ -986,10 +992,11 @@
986 @ if(aa==bb) return 0;
987 @ if(aa<bb) return -1;
988 @ return 1;
989 @ }
990 @ var thisObject = this;
 
991 @ var x = tableEl.getElementsByTagName('thead');
992 @ if(!(this.tbody && this.tbody[0].rows && this.tbody[0].rows.length>0)){
993 @ return;
994 @ }
995 @ if(x && x[0].rows && x[0].rows.length > 0) {
996
--- src/report.c
+++ src/report.c
@@ -928,13 +928,20 @@
928 **
929 ** http://www.webtoolkit.info/sortable-html-table.html
930 **
931 ** This variation allows column types to be expressed using the second
932 ** argument. Each character of the second argument represent a column.
933 **
934 ** t Sort by text
935 ** n Sort numerically
936 ** k Sort by the data-sortkey property
937 ** x This column is not sortable
938 **
939 ** If there are fewer characters in zColumnTypes[] than their are columns,
940 ** the all extra columns assume type "t" (text).
941 **
942 ** Clicking on the same column header twice in a row inverts the sort.
943 */
944 void output_table_sorting_javascript(const char *zTableId, const char *zColumnTypes){
945 @ <script>
946 @ function SortableTable(tableEl,columnTypes){
947 @ this.tbody = tableEl.getElementsByTagName('tbody');
@@ -950,16 +957,15 @@
957 @ this.sortIndex = column;
958 @ var newRows = new Array();
959 @ for (j = 0; j < this.tbody[0].rows.length; j++) {
960 @ newRows[j] = this.tbody[0].rows[j];
961 @ }
962 @ if( this.sortIndex==this.prevColumn ){
963 @ newRows.reverse();
964 @ }else{
965 @ newRows.sort(sortFn);
966 @ this.prevColumn = this.sortIndex;
 
967 @ }
968 @ for (i=0;i<newRows.length;i++) {
969 @ this.tbody[0].appendChild(newRows[i]);
970 @ }
971 @ }
@@ -986,10 +992,11 @@
992 @ if(aa==bb) return 0;
993 @ if(aa<bb) return -1;
994 @ return 1;
995 @ }
996 @ var thisObject = this;
997 @ var prevColumn = -1;
998 @ var x = tableEl.getElementsByTagName('thead');
999 @ if(!(this.tbody && this.tbody[0].rows && this.tbody[0].rows.length>0)){
1000 @ return;
1001 @ }
1002 @ if(x && x[0].rows && x[0].rows.length > 0) {
1003
--- src/style.c
+++ src/style.c
@@ -1275,10 +1275,11 @@
12751275
{ ".brlist table", "The list of branches",
12761276
@ border-spacing: 0;
12771277
},
12781278
{ ".brlist table th", "Branch list table headers",
12791279
@ text-align: left;
1280
+ @ padding: 0px 1em 0.5ex 0px;
12801281
},
12811282
{ ".brlist table td", "Branch list table headers",
12821283
@ padding: 0px 2em 0px 0px;
12831284
},
12841285
{ 0,
12851286
--- src/style.c
+++ src/style.c
@@ -1275,10 +1275,11 @@
1275 { ".brlist table", "The list of branches",
1276 @ border-spacing: 0;
1277 },
1278 { ".brlist table th", "Branch list table headers",
1279 @ text-align: left;
 
1280 },
1281 { ".brlist table td", "Branch list table headers",
1282 @ padding: 0px 2em 0px 0px;
1283 },
1284 { 0,
1285
--- src/style.c
+++ src/style.c
@@ -1275,10 +1275,11 @@
1275 { ".brlist table", "The list of branches",
1276 @ border-spacing: 0;
1277 },
1278 { ".brlist table th", "Branch list table headers",
1279 @ text-align: left;
1280 @ padding: 0px 1em 0.5ex 0px;
1281 },
1282 { ".brlist table td", "Branch list table headers",
1283 @ padding: 0px 2em 0px 0px;
1284 },
1285 { 0,
1286

Keyboard Shortcuts

Open search /
Next entry (timeline) j
Previous entry (timeline) k
Open focused entry Enter
Show this help ?
Toggle theme Top nav button