Fossil SCM
Add the "Last Change" activity report.
Commit
b629647e820a2f111e2eb2b2cfb14279fffaeda554c11c1c4f645698fc195b41
Parent
46d5d638b110ea9…
2 files changed
+1
+48
-2
+1
| --- src/setup.c | ||
| +++ src/setup.c | ||
| @@ -247,10 +247,11 @@ | ||
| 247 | 247 | @ <td>%h(zInfo) |
| 248 | 248 | @ <td>%h(zDate?zDate:"") |
| 249 | 249 | @ <td>%h(zExp?zExp:"") |
| 250 | 250 | @ <td data-sortkey='%f(rATime)' style='white-space:nowrap'>%s(zAge?zAge:"") |
| 251 | 251 | @ </tr> |
| 252 | + fossil_free(zAge); | |
| 252 | 253 | } |
| 253 | 254 | @ </tbody></table> |
| 254 | 255 | db_finalize(&s); |
| 255 | 256 | output_table_sorting_javascript("userlist","nktxTTK",2); |
| 256 | 257 | style_footer(); |
| 257 | 258 |
| --- src/setup.c | |
| +++ src/setup.c | |
| @@ -247,10 +247,11 @@ | |
| 247 | @ <td>%h(zInfo) |
| 248 | @ <td>%h(zDate?zDate:"") |
| 249 | @ <td>%h(zExp?zExp:"") |
| 250 | @ <td data-sortkey='%f(rATime)' style='white-space:nowrap'>%s(zAge?zAge:"") |
| 251 | @ </tr> |
| 252 | } |
| 253 | @ </tbody></table> |
| 254 | db_finalize(&s); |
| 255 | output_table_sorting_javascript("userlist","nktxTTK",2); |
| 256 | style_footer(); |
| 257 |
| --- src/setup.c | |
| +++ src/setup.c | |
| @@ -247,10 +247,11 @@ | |
| 247 | @ <td>%h(zInfo) |
| 248 | @ <td>%h(zDate?zDate:"") |
| 249 | @ <td>%h(zExp?zExp:"") |
| 250 | @ <td data-sortkey='%f(rATime)' style='white-space:nowrap'>%s(zAge?zAge:"") |
| 251 | @ </tr> |
| 252 | fossil_free(zAge); |
| 253 | } |
| 254 | @ </tbody></table> |
| 255 | db_finalize(&s); |
| 256 | output_table_sorting_javascript("userlist","nktxTTK",2); |
| 257 | style_footer(); |
| 258 |
+48
-2
| --- src/statrep.c | ||
| +++ src/statrep.c | ||
| @@ -639,19 +639,61 @@ | ||
| 639 | 639 | "Average per active week: %d</div>", |
| 640 | 640 | total, nAvg); |
| 641 | 641 | } |
| 642 | 642 | output_table_sorting_javascript("statsTable","tnx",-1); |
| 643 | 643 | } |
| 644 | + | |
| 645 | + | |
| 646 | +/* | |
| 647 | +** Generate a report that shows the most recent change for each user. | |
| 648 | +*/ | |
| 649 | +static void stats_report_last_change(void){ | |
| 650 | + Stmt s; | |
| 651 | + double rNow; | |
| 652 | + | |
| 653 | + stats_report_init_view(); | |
| 654 | + @ <table border=1 cellpadding=2 cellspacing=0 | |
| 655 | + @ class='lastchngTable' id='lastchng'> | |
| 656 | + @ <thead><tr> | |
| 657 | + @ <th>Username<th>Total Changes<th>Last Change</tr></thead> | |
| 658 | + @ <tbody> | |
| 659 | + db_prepare(&s, | |
| 660 | + "SELECT coalesce(euser,user)," | |
| 661 | + " count(*)," | |
| 662 | + " max(mtime)" | |
| 663 | + " FROM v_reports" | |
| 664 | + " GROUP BY 1" | |
| 665 | + " ORDER BY 3 DESC" | |
| 666 | + ); | |
| 667 | + rNow = db_double(0.0, "SELECT julianday('now');"); | |
| 668 | + while( db_step(&s)==SQLITE_ROW ){ | |
| 669 | + const char *zUser = db_column_text(&s, 0); | |
| 670 | + int cnt = db_column_int(&s, 1); | |
| 671 | + double rMTime = db_column_double(&s,2); | |
| 672 | + char *zAge = human_readable_age(rNow - rMTime); | |
| 673 | + @ <tr> | |
| 674 | + @ <td>%h(zUser)</a> | |
| 675 | + @ <td>%d(cnt) | |
| 676 | + @ <td data-sortkey='%f(rMTime)' style='white-space:nowrap'>%s(zAge?zAge:"") | |
| 677 | + @ </tr> | |
| 678 | + fossil_free(zAge); | |
| 679 | + } | |
| 680 | + @ </tbody></table> | |
| 681 | + db_finalize(&s); | |
| 682 | + output_table_sorting_javascript("userlist","tTK",3); | |
| 683 | +} | |
| 684 | + | |
| 644 | 685 | |
| 645 | 686 | /* Report types |
| 646 | 687 | */ |
| 647 | 688 | #define RPT_BYFILE 1 |
| 648 | 689 | #define RPT_BYMONTH 2 |
| 649 | 690 | #define RPT_BYUSER 3 |
| 650 | 691 | #define RPT_BYWEEK 4 |
| 651 | 692 | #define RPT_BYWEEKDAY 5 |
| 652 | 693 | #define RPT_BYYEAR 6 |
| 694 | +#define RPT_LASTCHNG 7 /* Last change made for each user */ | |
| 653 | 695 | #define RPT_NONE 0 /* None of the above */ |
| 654 | 696 | |
| 655 | 697 | /* |
| 656 | 698 | ** WEBPAGE: reports |
| 657 | 699 | ** |
| @@ -682,15 +724,16 @@ | ||
| 682 | 724 | const char *zName; /* Name of view= screen type */ |
| 683 | 725 | const char *zVal; /* Value of view= query parameter */ |
| 684 | 726 | int eType; /* Corresponding RPT_* define */ |
| 685 | 727 | } aViewType[] = { |
| 686 | 728 | { "File Changes","byfile", RPT_BYFILE }, |
| 729 | + { "Last Change", "lastchng", RPT_LASTCHNG }, | |
| 687 | 730 | { "By Month", "bymonth", RPT_BYMONTH }, |
| 688 | 731 | { "By User", "byuser", RPT_BYUSER }, |
| 689 | 732 | { "By Week", "byweek", RPT_BYWEEK }, |
| 690 | 733 | { "By Weekday", "byweekday", RPT_BYWEEKDAY }, |
| 691 | - { "By Year", "byyear", RPT_BYYEAR }, | |
| 734 | + { "By Year", "byyear", RPT_BYYEAR }, | |
| 692 | 735 | }; |
| 693 | 736 | static const char *const azType[] = { |
| 694 | 737 | "a", "All Changes", |
| 695 | 738 | "ci", "Check-ins", |
| 696 | 739 | "g", "Tags", |
| @@ -722,11 +765,11 @@ | ||
| 722 | 765 | } |
| 723 | 766 | if( eType!=RPT_BYFILE ){ |
| 724 | 767 | style_submenu_multichoice("type", count(azType)/2, azType, 0); |
| 725 | 768 | } |
| 726 | 769 | style_submenu_multichoice("view", nView/2, azView, 0); |
| 727 | - if( eType!=RPT_BYUSER ){ | |
| 770 | + if( eType!=RPT_BYUSER && eType!=RPT_LASTCHNG ){ | |
| 728 | 771 | style_submenu_sql("user","User:", |
| 729 | 772 | "SELECT '', 'All Users' UNION ALL " |
| 730 | 773 | "SELECT x, x FROM (" |
| 731 | 774 | " SELECT DISTINCT trim(coalesce(euser,user)) AS x FROM event %s" |
| 732 | 775 | " ORDER BY 1 COLLATE nocase) WHERE x!=''", |
| @@ -754,8 +797,11 @@ | ||
| 754 | 797 | stats_report_day_of_week(zUserName); |
| 755 | 798 | break; |
| 756 | 799 | case RPT_BYFILE: |
| 757 | 800 | stats_report_by_file(zUserName); |
| 758 | 801 | break; |
| 802 | + case RPT_LASTCHNG: | |
| 803 | + stats_report_last_change(); | |
| 804 | + break; | |
| 759 | 805 | } |
| 760 | 806 | style_footer(); |
| 761 | 807 | } |
| 762 | 808 |
| --- src/statrep.c | |
| +++ src/statrep.c | |
| @@ -639,19 +639,61 @@ | |
| 639 | "Average per active week: %d</div>", |
| 640 | total, nAvg); |
| 641 | } |
| 642 | output_table_sorting_javascript("statsTable","tnx",-1); |
| 643 | } |
| 644 | |
| 645 | /* Report types |
| 646 | */ |
| 647 | #define RPT_BYFILE 1 |
| 648 | #define RPT_BYMONTH 2 |
| 649 | #define RPT_BYUSER 3 |
| 650 | #define RPT_BYWEEK 4 |
| 651 | #define RPT_BYWEEKDAY 5 |
| 652 | #define RPT_BYYEAR 6 |
| 653 | #define RPT_NONE 0 /* None of the above */ |
| 654 | |
| 655 | /* |
| 656 | ** WEBPAGE: reports |
| 657 | ** |
| @@ -682,15 +724,16 @@ | |
| 682 | const char *zName; /* Name of view= screen type */ |
| 683 | const char *zVal; /* Value of view= query parameter */ |
| 684 | int eType; /* Corresponding RPT_* define */ |
| 685 | } aViewType[] = { |
| 686 | { "File Changes","byfile", RPT_BYFILE }, |
| 687 | { "By Month", "bymonth", RPT_BYMONTH }, |
| 688 | { "By User", "byuser", RPT_BYUSER }, |
| 689 | { "By Week", "byweek", RPT_BYWEEK }, |
| 690 | { "By Weekday", "byweekday", RPT_BYWEEKDAY }, |
| 691 | { "By Year", "byyear", RPT_BYYEAR }, |
| 692 | }; |
| 693 | static const char *const azType[] = { |
| 694 | "a", "All Changes", |
| 695 | "ci", "Check-ins", |
| 696 | "g", "Tags", |
| @@ -722,11 +765,11 @@ | |
| 722 | } |
| 723 | if( eType!=RPT_BYFILE ){ |
| 724 | style_submenu_multichoice("type", count(azType)/2, azType, 0); |
| 725 | } |
| 726 | style_submenu_multichoice("view", nView/2, azView, 0); |
| 727 | if( eType!=RPT_BYUSER ){ |
| 728 | style_submenu_sql("user","User:", |
| 729 | "SELECT '', 'All Users' UNION ALL " |
| 730 | "SELECT x, x FROM (" |
| 731 | " SELECT DISTINCT trim(coalesce(euser,user)) AS x FROM event %s" |
| 732 | " ORDER BY 1 COLLATE nocase) WHERE x!=''", |
| @@ -754,8 +797,11 @@ | |
| 754 | stats_report_day_of_week(zUserName); |
| 755 | break; |
| 756 | case RPT_BYFILE: |
| 757 | stats_report_by_file(zUserName); |
| 758 | break; |
| 759 | } |
| 760 | style_footer(); |
| 761 | } |
| 762 |
| --- src/statrep.c | |
| +++ src/statrep.c | |
| @@ -639,19 +639,61 @@ | |
| 639 | "Average per active week: %d</div>", |
| 640 | total, nAvg); |
| 641 | } |
| 642 | output_table_sorting_javascript("statsTable","tnx",-1); |
| 643 | } |
| 644 | |
| 645 | |
| 646 | /* |
| 647 | ** Generate a report that shows the most recent change for each user. |
| 648 | */ |
| 649 | static void stats_report_last_change(void){ |
| 650 | Stmt s; |
| 651 | double rNow; |
| 652 | |
| 653 | stats_report_init_view(); |
| 654 | @ <table border=1 cellpadding=2 cellspacing=0 |
| 655 | @ class='lastchngTable' id='lastchng'> |
| 656 | @ <thead><tr> |
| 657 | @ <th>Username<th>Total Changes<th>Last Change</tr></thead> |
| 658 | @ <tbody> |
| 659 | db_prepare(&s, |
| 660 | "SELECT coalesce(euser,user)," |
| 661 | " count(*)," |
| 662 | " max(mtime)" |
| 663 | " FROM v_reports" |
| 664 | " GROUP BY 1" |
| 665 | " ORDER BY 3 DESC" |
| 666 | ); |
| 667 | rNow = db_double(0.0, "SELECT julianday('now');"); |
| 668 | while( db_step(&s)==SQLITE_ROW ){ |
| 669 | const char *zUser = db_column_text(&s, 0); |
| 670 | int cnt = db_column_int(&s, 1); |
| 671 | double rMTime = db_column_double(&s,2); |
| 672 | char *zAge = human_readable_age(rNow - rMTime); |
| 673 | @ <tr> |
| 674 | @ <td>%h(zUser)</a> |
| 675 | @ <td>%d(cnt) |
| 676 | @ <td data-sortkey='%f(rMTime)' style='white-space:nowrap'>%s(zAge?zAge:"") |
| 677 | @ </tr> |
| 678 | fossil_free(zAge); |
| 679 | } |
| 680 | @ </tbody></table> |
| 681 | db_finalize(&s); |
| 682 | output_table_sorting_javascript("userlist","tTK",3); |
| 683 | } |
| 684 | |
| 685 | |
| 686 | /* Report types |
| 687 | */ |
| 688 | #define RPT_BYFILE 1 |
| 689 | #define RPT_BYMONTH 2 |
| 690 | #define RPT_BYUSER 3 |
| 691 | #define RPT_BYWEEK 4 |
| 692 | #define RPT_BYWEEKDAY 5 |
| 693 | #define RPT_BYYEAR 6 |
| 694 | #define RPT_LASTCHNG 7 /* Last change made for each user */ |
| 695 | #define RPT_NONE 0 /* None of the above */ |
| 696 | |
| 697 | /* |
| 698 | ** WEBPAGE: reports |
| 699 | ** |
| @@ -682,15 +724,16 @@ | |
| 724 | const char *zName; /* Name of view= screen type */ |
| 725 | const char *zVal; /* Value of view= query parameter */ |
| 726 | int eType; /* Corresponding RPT_* define */ |
| 727 | } aViewType[] = { |
| 728 | { "File Changes","byfile", RPT_BYFILE }, |
| 729 | { "Last Change", "lastchng", RPT_LASTCHNG }, |
| 730 | { "By Month", "bymonth", RPT_BYMONTH }, |
| 731 | { "By User", "byuser", RPT_BYUSER }, |
| 732 | { "By Week", "byweek", RPT_BYWEEK }, |
| 733 | { "By Weekday", "byweekday", RPT_BYWEEKDAY }, |
| 734 | { "By Year", "byyear", RPT_BYYEAR }, |
| 735 | }; |
| 736 | static const char *const azType[] = { |
| 737 | "a", "All Changes", |
| 738 | "ci", "Check-ins", |
| 739 | "g", "Tags", |
| @@ -722,11 +765,11 @@ | |
| 765 | } |
| 766 | if( eType!=RPT_BYFILE ){ |
| 767 | style_submenu_multichoice("type", count(azType)/2, azType, 0); |
| 768 | } |
| 769 | style_submenu_multichoice("view", nView/2, azView, 0); |
| 770 | if( eType!=RPT_BYUSER && eType!=RPT_LASTCHNG ){ |
| 771 | style_submenu_sql("user","User:", |
| 772 | "SELECT '', 'All Users' UNION ALL " |
| 773 | "SELECT x, x FROM (" |
| 774 | " SELECT DISTINCT trim(coalesce(euser,user)) AS x FROM event %s" |
| 775 | " ORDER BY 1 COLLATE nocase) WHERE x!=''", |
| @@ -754,8 +797,11 @@ | |
| 797 | stats_report_day_of_week(zUserName); |
| 798 | break; |
| 799 | case RPT_BYFILE: |
| 800 | stats_report_by_file(zUserName); |
| 801 | break; |
| 802 | case RPT_LASTCHNG: |
| 803 | stats_report_last_change(); |
| 804 | break; |
| 805 | } |
| 806 | style_footer(); |
| 807 | } |
| 808 |