Fossil SCM
Use drop-down menus to select the user on the /reports pages.
Commit
675274612dc320046b8887070218ba9fc9238f65
Parent
5fa4d0125cbd7bf…
2 files changed
+16
-22
+37
+16
-22
| --- src/statrep.c | ||
| +++ src/statrep.c | ||
| @@ -577,31 +577,19 @@ | ||
| 577 | 577 | char **azYear = 0; /* Year dropdown menu */ |
| 578 | 578 | int rowCount = 0; |
| 579 | 579 | int total = 0; |
| 580 | 580 | |
| 581 | 581 | stats_report_init_view(); |
| 582 | - db_prepare(&q, | |
| 583 | - "SELECT DISTINCT substr(date(mtime),1,4) AS y" | |
| 584 | - " FROM v_reports" | |
| 585 | - " WHERE ifnull(coalesce(euser,user,'')=%Q,1)" | |
| 586 | - " GROUP BY y ORDER BY y DESC", zUserName); | |
| 587 | - while( SQLITE_ROW == db_step(&q) ){ | |
| 588 | - azYear = fossil_realloc(azYear, sizeof(char*)*(n+2)); | |
| 589 | - azYear[n] = fossil_strdup(db_column_text(&q,0)); | |
| 590 | - azYear[n+1] = azYear[n]; | |
| 591 | - if( !isValidYear && fossil_strcmp(zYear,azYear[n])==0 ) isValidYear = 1; | |
| 592 | - n += 2; | |
| 593 | - } | |
| 594 | - db_finalize(&q); | |
| 595 | - if( !isValidYear ){ | |
| 596 | - if( n ){ | |
| 597 | - zYear = azYear[0]; | |
| 598 | - }else{ | |
| 599 | - zYear = db_text("1970","SELECT substr(date('now'),1,4);"); | |
| 600 | - } | |
| 601 | - } | |
| 602 | - style_submenu_multichoice("y", n/2, (const char**)azYear, 0); | |
| 582 | + style_submenu_sql("y", "Year:", | |
| 583 | + "WITH RECURSIVE a(b) AS (" | |
| 584 | + " SELECT substr(date('now'),1,4) UNION ALL" | |
| 585 | + " SELECT b-1 FROM a" | |
| 586 | + " WHERE b>0+(SELECT substr(date(min(mtime)),1,4) FROM event)" | |
| 587 | + ") SELECT b, b FROM a ORDER BY b DESC"); | |
| 588 | + if( zYear==0 || strlen(zYear)!=4 ){ | |
| 589 | + zYear = db_text("1970","SELECT substr(date('now'),1,4);"); | |
| 590 | + } | |
| 603 | 591 | cgi_printf("<br/>"); |
| 604 | 592 | db_prepare(&q, |
| 605 | 593 | "SELECT DISTINCT strftime('%%W',mtime) AS wk, " |
| 606 | 594 | " count(*) AS n " |
| 607 | 595 | " FROM v_reports " |
| @@ -753,11 +741,17 @@ | ||
| 753 | 741 | style_submenu_multichoice("view", nView/2, azView, 0); |
| 754 | 742 | if( eType!=RPT_BYFILE ){ |
| 755 | 743 | style_submenu_multichoice("type", ArraySize(azType)/2, azType, 0); |
| 756 | 744 | } |
| 757 | 745 | if( eType!=RPT_BYUSER ){ |
| 758 | - style_submenu_entry("u", "User:", 12, 0); | |
| 746 | + style_submenu_sql("u","User:", | |
| 747 | + "SELECT '', 'All Users' UNION ALL " | |
| 748 | + "SELECT x, x FROM (" | |
| 749 | + " SELECT DISTINCT trim(coalesce(euser,user)) AS x FROM event %s" | |
| 750 | + " ORDER BY 1 COLLATE nocase) WHERE x!=''", | |
| 751 | + eType==RPT_BYFILE ? "WHERE type='ci'" : "" | |
| 752 | + ); | |
| 759 | 753 | } |
| 760 | 754 | } |
| 761 | 755 | style_submenu_element("Stats", "Stats", "%R/stat"); |
| 762 | 756 | url_reset(&url); |
| 763 | 757 | style_header("Activity Reports"); |
| 764 | 758 |
| --- src/statrep.c | |
| +++ src/statrep.c | |
| @@ -577,31 +577,19 @@ | |
| 577 | char **azYear = 0; /* Year dropdown menu */ |
| 578 | int rowCount = 0; |
| 579 | int total = 0; |
| 580 | |
| 581 | stats_report_init_view(); |
| 582 | db_prepare(&q, |
| 583 | "SELECT DISTINCT substr(date(mtime),1,4) AS y" |
| 584 | " FROM v_reports" |
| 585 | " WHERE ifnull(coalesce(euser,user,'')=%Q,1)" |
| 586 | " GROUP BY y ORDER BY y DESC", zUserName); |
| 587 | while( SQLITE_ROW == db_step(&q) ){ |
| 588 | azYear = fossil_realloc(azYear, sizeof(char*)*(n+2)); |
| 589 | azYear[n] = fossil_strdup(db_column_text(&q,0)); |
| 590 | azYear[n+1] = azYear[n]; |
| 591 | if( !isValidYear && fossil_strcmp(zYear,azYear[n])==0 ) isValidYear = 1; |
| 592 | n += 2; |
| 593 | } |
| 594 | db_finalize(&q); |
| 595 | if( !isValidYear ){ |
| 596 | if( n ){ |
| 597 | zYear = azYear[0]; |
| 598 | }else{ |
| 599 | zYear = db_text("1970","SELECT substr(date('now'),1,4);"); |
| 600 | } |
| 601 | } |
| 602 | style_submenu_multichoice("y", n/2, (const char**)azYear, 0); |
| 603 | cgi_printf("<br/>"); |
| 604 | db_prepare(&q, |
| 605 | "SELECT DISTINCT strftime('%%W',mtime) AS wk, " |
| 606 | " count(*) AS n " |
| 607 | " FROM v_reports " |
| @@ -753,11 +741,17 @@ | |
| 753 | style_submenu_multichoice("view", nView/2, azView, 0); |
| 754 | if( eType!=RPT_BYFILE ){ |
| 755 | style_submenu_multichoice("type", ArraySize(azType)/2, azType, 0); |
| 756 | } |
| 757 | if( eType!=RPT_BYUSER ){ |
| 758 | style_submenu_entry("u", "User:", 12, 0); |
| 759 | } |
| 760 | } |
| 761 | style_submenu_element("Stats", "Stats", "%R/stat"); |
| 762 | url_reset(&url); |
| 763 | style_header("Activity Reports"); |
| 764 |
| --- src/statrep.c | |
| +++ src/statrep.c | |
| @@ -577,31 +577,19 @@ | |
| 577 | char **azYear = 0; /* Year dropdown menu */ |
| 578 | int rowCount = 0; |
| 579 | int total = 0; |
| 580 | |
| 581 | stats_report_init_view(); |
| 582 | style_submenu_sql("y", "Year:", |
| 583 | "WITH RECURSIVE a(b) AS (" |
| 584 | " SELECT substr(date('now'),1,4) UNION ALL" |
| 585 | " SELECT b-1 FROM a" |
| 586 | " WHERE b>0+(SELECT substr(date(min(mtime)),1,4) FROM event)" |
| 587 | ") SELECT b, b FROM a ORDER BY b DESC"); |
| 588 | if( zYear==0 || strlen(zYear)!=4 ){ |
| 589 | zYear = db_text("1970","SELECT substr(date('now'),1,4);"); |
| 590 | } |
| 591 | cgi_printf("<br/>"); |
| 592 | db_prepare(&q, |
| 593 | "SELECT DISTINCT strftime('%%W',mtime) AS wk, " |
| 594 | " count(*) AS n " |
| 595 | " FROM v_reports " |
| @@ -753,11 +741,17 @@ | |
| 741 | style_submenu_multichoice("view", nView/2, azView, 0); |
| 742 | if( eType!=RPT_BYFILE ){ |
| 743 | style_submenu_multichoice("type", ArraySize(azType)/2, azType, 0); |
| 744 | } |
| 745 | if( eType!=RPT_BYUSER ){ |
| 746 | style_submenu_sql("u","User:", |
| 747 | "SELECT '', 'All Users' UNION ALL " |
| 748 | "SELECT x, x FROM (" |
| 749 | " SELECT DISTINCT trim(coalesce(euser,user)) AS x FROM event %s" |
| 750 | " ORDER BY 1 COLLATE nocase) WHERE x!=''", |
| 751 | eType==RPT_BYFILE ? "WHERE type='ci'" : "" |
| 752 | ); |
| 753 | } |
| 754 | } |
| 755 | style_submenu_element("Stats", "Stats", "%R/stat"); |
| 756 | url_reset(&url); |
| 757 | style_header("Activity Reports"); |
| 758 |
+37
| --- src/style.c | ||
| +++ src/style.c | ||
| @@ -285,11 +285,45 @@ | ||
| 285 | 285 | aSubmenuCtrl[nSubmenuCtrl].azChoice = azChoice; |
| 286 | 286 | aSubmenuCtrl[nSubmenuCtrl].isDisabled = isDisabled; |
| 287 | 287 | aSubmenuCtrl[nSubmenuCtrl].eType = FF_MULTI; |
| 288 | 288 | nSubmenuCtrl++; |
| 289 | 289 | } |
| 290 | +void style_submenu_sql( | |
| 291 | + const char *zName, /* Query parameter name */ | |
| 292 | + const char *zLabel, /* Label on the control */ | |
| 293 | + const char *zFormat, /* Format string for SQL command for choices */ | |
| 294 | + ... /* Arguments to the format string */ | |
| 295 | +){ | |
| 296 | + Stmt q; | |
| 297 | + int n = 0; | |
| 298 | + int nAlloc = 0; | |
| 299 | + char **az = 0; | |
| 300 | + va_list ap; | |
| 290 | 301 | |
| 302 | + va_start(ap, zFormat); | |
| 303 | + db_vprepare(&q, 0, zFormat, ap); | |
| 304 | + va_end(ap); | |
| 305 | + while( SQLITE_ROW==db_step(&q) ){ | |
| 306 | + if( n+2>=nAlloc ){ | |
| 307 | + nAlloc += nAlloc + 20; | |
| 308 | + az = fossil_realloc(az, sizeof(char*)*nAlloc); | |
| 309 | + } | |
| 310 | + az[n++] = fossil_strdup(db_column_text(&q,0)); | |
| 311 | + az[n++] = fossil_strdup(db_column_text(&q,1)); | |
| 312 | + } | |
| 313 | + db_finalize(&q); | |
| 314 | + if( n>0 ){ | |
| 315 | + aSubmenuCtrl[nSubmenuCtrl].zName = zName; | |
| 316 | + aSubmenuCtrl[nSubmenuCtrl].zLabel = zLabel; | |
| 317 | + aSubmenuCtrl[nSubmenuCtrl].iSize = n/2; | |
| 318 | + aSubmenuCtrl[nSubmenuCtrl].azChoice = (const char**)az; | |
| 319 | + aSubmenuCtrl[nSubmenuCtrl].isDisabled = 0; | |
| 320 | + aSubmenuCtrl[nSubmenuCtrl].eType = FF_MULTI; | |
| 321 | + nSubmenuCtrl++; | |
| 322 | + } | |
| 323 | +} | |
| 324 | + | |
| 291 | 325 | |
| 292 | 326 | /* |
| 293 | 327 | ** Compare two submenu items for sorting purposes |
| 294 | 328 | */ |
| 295 | 329 | static int submenuCompare(const void *a, const void *b){ |
| @@ -514,10 +548,13 @@ | ||
| 514 | 548 | break; |
| 515 | 549 | } |
| 516 | 550 | case FF_MULTI: { |
| 517 | 551 | int j; |
| 518 | 552 | const char *zVal = P(zQPN); |
| 553 | + if( aSubmenuCtrl[i].zLabel ){ | |
| 554 | + cgi_printf(" %h", aSubmenuCtrl[i].zLabel); | |
| 555 | + } | |
| 519 | 556 | cgi_printf( |
| 520 | 557 | "<select class='submenuctrl' size='1' name='%s'%s " |
| 521 | 558 | "onchange='gebi(\"f01\").submit();'>\n", |
| 522 | 559 | zQPN, zDisabled |
| 523 | 560 | ); |
| 524 | 561 |
| --- src/style.c | |
| +++ src/style.c | |
| @@ -285,11 +285,45 @@ | |
| 285 | aSubmenuCtrl[nSubmenuCtrl].azChoice = azChoice; |
| 286 | aSubmenuCtrl[nSubmenuCtrl].isDisabled = isDisabled; |
| 287 | aSubmenuCtrl[nSubmenuCtrl].eType = FF_MULTI; |
| 288 | nSubmenuCtrl++; |
| 289 | } |
| 290 | |
| 291 | |
| 292 | /* |
| 293 | ** Compare two submenu items for sorting purposes |
| 294 | */ |
| 295 | static int submenuCompare(const void *a, const void *b){ |
| @@ -514,10 +548,13 @@ | |
| 514 | break; |
| 515 | } |
| 516 | case FF_MULTI: { |
| 517 | int j; |
| 518 | const char *zVal = P(zQPN); |
| 519 | cgi_printf( |
| 520 | "<select class='submenuctrl' size='1' name='%s'%s " |
| 521 | "onchange='gebi(\"f01\").submit();'>\n", |
| 522 | zQPN, zDisabled |
| 523 | ); |
| 524 |
| --- src/style.c | |
| +++ src/style.c | |
| @@ -285,11 +285,45 @@ | |
| 285 | aSubmenuCtrl[nSubmenuCtrl].azChoice = azChoice; |
| 286 | aSubmenuCtrl[nSubmenuCtrl].isDisabled = isDisabled; |
| 287 | aSubmenuCtrl[nSubmenuCtrl].eType = FF_MULTI; |
| 288 | nSubmenuCtrl++; |
| 289 | } |
| 290 | void style_submenu_sql( |
| 291 | const char *zName, /* Query parameter name */ |
| 292 | const char *zLabel, /* Label on the control */ |
| 293 | const char *zFormat, /* Format string for SQL command for choices */ |
| 294 | ... /* Arguments to the format string */ |
| 295 | ){ |
| 296 | Stmt q; |
| 297 | int n = 0; |
| 298 | int nAlloc = 0; |
| 299 | char **az = 0; |
| 300 | va_list ap; |
| 301 | |
| 302 | va_start(ap, zFormat); |
| 303 | db_vprepare(&q, 0, zFormat, ap); |
| 304 | va_end(ap); |
| 305 | while( SQLITE_ROW==db_step(&q) ){ |
| 306 | if( n+2>=nAlloc ){ |
| 307 | nAlloc += nAlloc + 20; |
| 308 | az = fossil_realloc(az, sizeof(char*)*nAlloc); |
| 309 | } |
| 310 | az[n++] = fossil_strdup(db_column_text(&q,0)); |
| 311 | az[n++] = fossil_strdup(db_column_text(&q,1)); |
| 312 | } |
| 313 | db_finalize(&q); |
| 314 | if( n>0 ){ |
| 315 | aSubmenuCtrl[nSubmenuCtrl].zName = zName; |
| 316 | aSubmenuCtrl[nSubmenuCtrl].zLabel = zLabel; |
| 317 | aSubmenuCtrl[nSubmenuCtrl].iSize = n/2; |
| 318 | aSubmenuCtrl[nSubmenuCtrl].azChoice = (const char**)az; |
| 319 | aSubmenuCtrl[nSubmenuCtrl].isDisabled = 0; |
| 320 | aSubmenuCtrl[nSubmenuCtrl].eType = FF_MULTI; |
| 321 | nSubmenuCtrl++; |
| 322 | } |
| 323 | } |
| 324 | |
| 325 | |
| 326 | /* |
| 327 | ** Compare two submenu items for sorting purposes |
| 328 | */ |
| 329 | static int submenuCompare(const void *a, const void *b){ |
| @@ -514,10 +548,13 @@ | |
| 548 | break; |
| 549 | } |
| 550 | case FF_MULTI: { |
| 551 | int j; |
| 552 | const char *zVal = P(zQPN); |
| 553 | if( aSubmenuCtrl[i].zLabel ){ |
| 554 | cgi_printf(" %h", aSubmenuCtrl[i].zLabel); |
| 555 | } |
| 556 | cgi_printf( |
| 557 | "<select class='submenuctrl' size='1' name='%s'%s " |
| 558 | "onchange='gebi(\"f01\").submit();'>\n", |
| 559 | zQPN, zDisabled |
| 560 | ); |
| 561 |