Many hyperlinks are disabled.
Use anonymous login
to enable hyperlinks.
Overview
| Comment: | Add a by-hour-of-day report to the /reports page, prompted by a /chat discussion. (Edit: initial user mis-attribution was caused by a config-pull which changed my local default user.) |
|---|---|
| Downloads: | Tarball | ZIP archive |
| Timelines: | family | ancestors | descendants | both | trunk |
| Files: | files | file ages | folders |
| SHA3-256: |
bb6f23313ed6e48a322d41b210da4130 |
| User & Date: | stephan 2022-10-18 16:17:23.294 |
| Original Comment: | Add a by-hour-of-day report to the /reports page, prompted by a /chat discussion. |
| Original User & Date: | drh 2022-10-18 16:17:23.294 |
Context
|
2022-10-18
| ||
| 16:55 | Cache get_comment_format() result to avoid that the global config db is queried once per timeline row, which brings fossil to a standstill when ~/ is NFS-mounted. Discussion in [forum:9aaefe4e536e01bf]. ... (check-in: 6e62c8510f user: stephan tags: trunk) | |
| 16:17 | Add a by-hour-of-day report to the /reports page, prompted by a /chat discussion. (Edit: initial user mis-attribution was caused by a config-pull which changed my local default user.) ... (check-in: bb6f23313e user: stephan tags: trunk) | |
| 13:35 | For the BUILTIN virtual table, map one-based rowids to zero-based array indices, to fix access to the first entry. ... (check-in: cf563c7217 user: florian tags: trunk) | |
Changes
Changes to src/statrep.c.
| ︙ | ︙ | |||
195 196 197 198 199 200 201 |
current year */
char showYearTotal = 0; /* Flag telling us when to show
the per-year event totals */
int nMaxEvents = 1; /* for calculating length of graph
bars. */
int iterations = 0; /* number of weeks/months we iterate
over */
| < < < < < | 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 |
current year */
char showYearTotal = 0; /* Flag telling us when to show
the per-year event totals */
int nMaxEvents = 1; /* for calculating length of graph
bars. */
int iterations = 0; /* number of weeks/months we iterate
over */
stats_report_init_view();
db_prepare(&query,
"SELECT substr(date(mtime),1,%d) AS timeframe,"
" count(*) AS eventCount"
" FROM v_reports"
" WHERE ifnull(coalesce(euser,user,'')=%Q,1)"
" GROUP BY timeframe"
" ORDER BY timeframe DESC",
|
| ︙ | ︙ | |||
475 476 477 478 479 480 481 |
static void stats_report_day_of_week(const char *zUserName){
Stmt query = empty_Stmt;
int nRowNumber = 0; /* current TR number */
int rowClass = 0; /* counter for alternating
row colors */
int nMaxEvents = 1; /* max number of events for
all rows. */
| < < < < | 470 471 472 473 474 475 476 477 478 479 480 481 482 483 484 485 486 487 488 489 |
static void stats_report_day_of_week(const char *zUserName){
Stmt query = empty_Stmt;
int nRowNumber = 0; /* current TR number */
int rowClass = 0; /* counter for alternating
row colors */
int nMaxEvents = 1; /* max number of events for
all rows. */
static const char *const daysOfWeek[] = {
"Sunday", "Monday", "Tuesday", "Wednesday",
"Thursday", "Friday", "Saturday"
};
stats_report_init_view();
db_prepare(&query,
"SELECT cast(strftime('%%w', mtime) AS INTEGER) dow,"
" COUNT(*) AS eventCount"
" FROM v_reports"
" WHERE ifnull(coalesce(euser,user,'')=%Q,1)"
" GROUP BY dow ORDER BY dow", zUserName);
@ <h1>Timeline Events (%h(stats_report_label_for_type())) by Day of the Week
|
| ︙ | ︙ | |||
548 549 550 551 552 553 554 555 556 557 558 559 560 561 |
if(!nCount) continue /* arguable! Possible? */;
else if(!nSize) nSize = 1;
rowClass = ++nRowNumber % 2;
@<tr class='row%d(rowClass)'>
@ <td>%d(dayNum)</td>
@ <td>%s(daysOfWeek[dayNum])</td>
@ <td>%d(nCount)</td>
@ <td>
@ <div class='statistics-report-graph-line'
@ style='width:%d(nSize)%%;'> </div>
@ </td>
@</tr>
}
@ </tbody></table>
| > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | 539 540 541 542 543 544 545 546 547 548 549 550 551 552 553 554 555 556 557 558 559 560 561 562 563 564 565 566 567 568 569 570 571 572 573 574 575 576 577 578 579 580 581 582 583 584 585 586 587 588 589 590 591 592 593 594 595 596 597 598 599 600 601 602 603 604 605 606 607 608 609 610 611 612 613 614 615 616 617 618 619 620 621 622 623 624 625 626 627 |
if(!nCount) continue /* arguable! Possible? */;
else if(!nSize) nSize = 1;
rowClass = ++nRowNumber % 2;
@<tr class='row%d(rowClass)'>
@ <td>%d(dayNum)</td>
@ <td>%s(daysOfWeek[dayNum])</td>
@ <td>%d(nCount)</td>
@ <td>
@ <div class='statistics-report-graph-line'
@ style='width:%d(nSize)%%;'> </div>
@ </td>
@</tr>
}
@ </tbody></table>
db_finalize(&query);
}
/*
** Implements the "byhour" view for /reports. If zUserName is not NULL
** then the report is restricted to events created by the named user
** account.
*/
static void stats_report_hour_of_day(const char *zUserName){
Stmt query = empty_Stmt;
int nRowNumber = 0; /* current TR number */
int rowClass = 0; /* counter for alternating
row colors */
int nMaxEvents = 1; /* max number of events for
all rows. */
stats_report_init_view();
db_prepare(&query,
"SELECT cast(strftime('%%H', mtime) AS INTEGER) hod,"
" COUNT(*) AS eventCount"
" FROM v_reports"
" WHERE ifnull(coalesce(euser,user,'')=%Q,1)"
" GROUP BY hod ORDER BY hod", zUserName);
@ <h1>Timeline Events (%h(stats_report_label_for_type())) by Hour of Day
if( zUserName ){
@ for user %h(zUserName)
}
@ </h1>
db_multi_exec(
"CREATE TEMP VIEW piechart(amt,label) AS"
" SELECT count(*), strftime('%%H', mtime) hod"
" FROM v_reports"
" WHERE ifnull(coalesce(euser,user,'')=%Q,1)"
" GROUP BY 2 ORDER BY hod;",
zUserName
);
if( db_int(0, "SELECT count(*) FROM piechart")>=2 ){
@ <center><svg width=700 height=400>
piechart_render(700, 400, PIE_OTHER|PIE_PERCENT);
@ </svg></centre><hr />
}
style_table_sorter();
@ <table class='statistics-report-table-events sortable' border='0' \
@ cellpadding='2' cellspacing='0' data-column-types='nnx' data-init-sort='1'>
@ <thead><tr>
@ <th>Hour</th>
@ <th>Events</th>
@ <th width='90%%'><!-- relative commits graph --></th>
@ </tr></thead><tbody>
while( SQLITE_ROW == db_step(&query) ){
const int nCount = db_column_int(&query, 1);
if(nCount>nMaxEvents){
nMaxEvents = nCount;
}
}
db_reset(&query);
while( SQLITE_ROW == db_step(&query) ){
const int hourNum =db_column_int(&query, 0);
const int nCount = db_column_int(&query, 1);
int nSize = nCount
? (int)(100 * nCount / nMaxEvents)
: 0;
if(!nCount) continue /* arguable! Possible? */;
else if(!nSize) nSize = 1;
rowClass = ++nRowNumber % 2;
@<tr class='row%d(rowClass)'>
@ <td>%d(hourNum)</td>
@ <td>%d(nCount)</td>
@ <td>
@ <div class='statistics-report-graph-line'
@ style='width:%d(nSize)%%;'> </div>
@ </td>
@</tr>
}
@ </tbody></table>
|
| ︙ | ︙ | |||
707 708 709 710 711 712 713 714 715 716 717 718 719 720 | #define RPT_BYFILE 1 #define RPT_BYMONTH 2 #define RPT_BYUSER 3 #define RPT_BYWEEK 4 #define RPT_BYWEEKDAY 5 #define RPT_BYYEAR 6 #define RPT_LASTCHNG 7 /* Last change made for each user */ #define RPT_NONE 0 /* None of the above */ /* ** WEBPAGE: reports ** ** Shows activity reports for the repository. ** | > | 773 774 775 776 777 778 779 780 781 782 783 784 785 786 787 | #define RPT_BYFILE 1 #define RPT_BYMONTH 2 #define RPT_BYUSER 3 #define RPT_BYWEEK 4 #define RPT_BYWEEKDAY 5 #define RPT_BYYEAR 6 #define RPT_LASTCHNG 7 /* Last change made for each user */ #define RPT_BYHOUR 8 /* hour-of-day */ #define RPT_NONE 0 /* None of the above */ /* ** WEBPAGE: reports ** ** Shows activity reports for the repository. ** |
| ︙ | ︙ | |||
747 748 749 750 751 752 753 754 755 756 757 758 759 760 |
{ "File Changes","byfile", RPT_BYFILE },
{ "Last Change", "lastchng", RPT_LASTCHNG },
{ "By Month", "bymonth", RPT_BYMONTH },
{ "By User", "byuser", RPT_BYUSER },
{ "By Week", "byweek", RPT_BYWEEK },
{ "By Weekday", "byweekday", RPT_BYWEEKDAY },
{ "By Year", "byyear", RPT_BYYEAR },
};
static const char *const azType[] = {
"a", "All Changes",
"ci", "Check-ins",
"f", "Forum Posts",
"g", "Tags",
"e", "Tech Notes",
| > | 814 815 816 817 818 819 820 821 822 823 824 825 826 827 828 |
{ "File Changes","byfile", RPT_BYFILE },
{ "Last Change", "lastchng", RPT_LASTCHNG },
{ "By Month", "bymonth", RPT_BYMONTH },
{ "By User", "byuser", RPT_BYUSER },
{ "By Week", "byweek", RPT_BYWEEK },
{ "By Weekday", "byweekday", RPT_BYWEEKDAY },
{ "By Year", "byyear", RPT_BYYEAR },
{ "By Hour", "byhour", RPT_BYHOUR },
};
static const char *const azType[] = {
"a", "All Changes",
"ci", "Check-ins",
"f", "Forum Posts",
"g", "Tags",
"e", "Tech Notes",
|
| ︙ | ︙ | |||
815 816 817 818 819 820 821 822 823 824 825 826 827 |
break;
case RPT_BYWEEKDAY:
stats_report_day_of_week(zUserName);
break;
case RPT_BYFILE:
stats_report_by_file(zUserName);
break;
case RPT_LASTCHNG:
stats_report_last_change();
break;
}
style_finish_page();
}
| > > > | 883 884 885 886 887 888 889 890 891 892 893 894 895 896 897 898 |
break;
case RPT_BYWEEKDAY:
stats_report_day_of_week(zUserName);
break;
case RPT_BYFILE:
stats_report_by_file(zUserName);
break;
case RPT_BYHOUR:
stats_report_hour_of_day(zUserName);
break;
case RPT_LASTCHNG:
stats_report_last_change();
break;
}
style_finish_page();
}
|
Changes to www/changes.wiki.
| ︙ | ︙ | |||
9 10 11 12 13 14 15 16 17 18 19 20 21 22 |
* More elements of the /info page are now inside of an accordion.
* Replace the <tt>--dryrun</tt> flag with <tt>--dry-run</tt> in all
commands which still used the former name, for consistency.
* Rebuilt [/file/Dockerfile | the stock Dockerfile] to create a "from scratch"
Busybox based container image via an Alpine Linux intermediary
* Added [/doc/trunk/www/containers.md | a new document] describing how to
customize, use, and run that container.
<h2 id='v2_19'>Changes for version 2.19 (2022-07-21)</h2>
* On file listing pages, sort filenames using the "uintnocase" collating
sequence, so that filenames that contains embedded integers sort in
numeric order even if they contain a different number of digits.
(Example: "fossil_80_..." comes before "fossil_100.png" in the
[/dir?ci=92fd091703a28c07&name=skins/blitz|/skins/blitz] directory listing.)
| > | 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 |
* More elements of the /info page are now inside of an accordion.
* Replace the <tt>--dryrun</tt> flag with <tt>--dry-run</tt> in all
commands which still used the former name, for consistency.
* Rebuilt [/file/Dockerfile | the stock Dockerfile] to create a "from scratch"
Busybox based container image via an Alpine Linux intermediary
* Added [/doc/trunk/www/containers.md | a new document] describing how to
customize, use, and run that container.
* Added "by hour of day" report to [/reports?view=byhour|the /reports page].
<h2 id='v2_19'>Changes for version 2.19 (2022-07-21)</h2>
* On file listing pages, sort filenames using the "uintnocase" collating
sequence, so that filenames that contains embedded integers sort in
numeric order even if they contain a different number of digits.
(Example: "fossil_80_..." comes before "fossil_100.png" in the
[/dir?ci=92fd091703a28c07&name=skins/blitz|/skins/blitz] directory listing.)
|
| ︙ | ︙ |