/**
Utilities for importing from the various reports-* pages.
*/
return proc(ns){
ns.createAnchor = proc(page, label, urlParams){
const opt = object {
year: this.year,
type: this.eventType,
user: this.user,
yearWeek: util.yearWeek,
limit: this.limit
}
urlParams || (urlParams = object{})
assert 'object' === typename urlParams
opt.eachProperty(proc(k,v){
urlParams.hasOwnProperty(k) || urlParams.set(k,v)
})
('*'===urlParams.type) && unset urlParams.type
return api.cgi.html.createAnchor( api.cgi.cgiRoot + page +
'?'+api.cgi.objToUrlParams(urlParams),
label)
}
ns.getYearList = proc(){
const aYears = array[]
var stmt = api.cgi.getFossilInstance().db.prepare(
{SELECT DISTINCT substr(date(mtime),1,4) AS y
FROM /*v_reports*/ event GROUP BY y ORDER BY y})
while(stmt.step()){
aYears.push( stmt.get(0) )
}
stmt.finalize()
return aYears
}
ns.generateYearSelection = proc(urlParams){
const CGI = api.cgi
const aYears = this.getYearList()
aYears.length() || return
const out = api.io.output
const filterYear = this.linkProps.year
urlParams || (urlParams = object{})
Fossil.extendProperties(this.linkProps, urlParams)
unset urlParams.yearWeek, urlParams.yearMonth
$out {<div class='reports-filter-year'>Select year:} ' '
// th1ish bug: assertion crash: ((this.eventType==='*') ? undefined : this.eventType)
if(filterYear){
$out "<a href='?" CGI.objToUrlParams(object{
user: this.linkProps.user,
type: this.linkProps.type,
limit: this.linkProps.limit
}) "'"
//filterYear || $out " class='active'"
$out {>all</a>}
}else{
$out {<span class='active'>all</span>}
}
aYears.eachIndex(proc(y){
urlParams.year = y
if(1){
if(y===filterYear){
$out " <span class='active'>" y {</span>}
}else{
$out " <a href='?" CGI.objToUrlParams(urlParams) "'>" y {</a>}
}
}else{
$out " <a href='?" CGI.objToUrlParams(urlParams) "'"
if(y === filterYear){
$out " class='active'"
}
$out ">" y {</a>}
}
})
$out {</div>}
}
ns.initReportsView2 = proc(opt){
const CGI = api.cgi
const optDefaults = object{
filterOnTime: true,
filterOnUser: true,
showFilterLimit: false
}
opt || (opt = object{})
Fossil.extendProperties(optDefaults, opt)
var eventType = this.eventType = (CGI.getVar('type') || '*')
const sql = api.Buffer(200)
sql.appendf({CREATE TEMP VIEW v_reports AS
SELECT * FROM event WHERE type GLOB %1$Q},
this.eventType)
this.user = CGI.getVar('user')
if(this.user && opt.filterOnUser){
sql.appendf(' AND user=%1$Q', this.user)
}
/* Link parameters we commonly want to propagate */
this.linkProps.limit = +CGI.getVar('limit') || undefined
this.linkProps.user = this.user
if(opt.filterOnTime){
var timePart = (opt.year || CGI.getVar('year'))
if(Fossil.globMatches({[12][0-9][0-9][0-9]}, timePart)){
this.linkProps.year = this.year = timePart
sql.appendf(' AND strftime("%%Y",mtime)=%1$Q', timePart)
}else if(timePart && ('integer' !==typename timePart)){
throw "Bad year value: "+timePart
}
timePart = (opt.dateTime || CGI.getVar('dateTime'))
if(timePart){
sql.appendf(" AND datetime(mtime) LIKE '%1$q%%'", timePart)
}
timePart = (opt.yearMonth || CGI.getVar('yearMonth'))
if(Fossil.globMatches({[12][0-9][0-9][0-9]-[0-2][0-9]}, timePart)){
this.linkProps.yearMonth = timePart
sql.appendf(' AND strftime("%%Y-%%m",mtime)=%1$Q', timePart)
}else if(timePart){
throw "Bad yearMonth value: "+timePart
}
timePart = (opt.yearWeek || CGI.getVar('yearWeek'))
if(Fossil.globMatches({[12][0-9][0-9][0-9]-[0-6][0-9]}, timePart)){
this.linkProps.yearWeek = timePart
sql.appendf(' AND strftime("%%Y-%%W",mtime)=%1$Q', timePart)
}else if(timePart){
throw "Bad yearWeek value: "+timePart
}
}
if(this.eventType && ('*'!==this.eventType)){
this.linkProps.type = this.eventType
}
//api.io.output(sql)
F.db.exec(sql)
this.generateSubmenu()
this.generateTypeLinks()
this.generateYearSelection()
opt.showFilterLimit && this.generateLimitLinks()
return true
}
const typeMap = object{
'*': 'all',
ci: 'checkins',
w: 'wiki',
g: 'tags',
e: 'events',
t: 'tickets'
}
ns.getEventTypeLabel = proc(){
('*'===this.eventType) && return 'all types'
return typeMap.(this.eventType)
}.importSymbols(nameof typeMap)
ns.generateTypeLinks = proc(linkObj){
const CGI = api.cgi
const out = api.io.output
const currentEventType = (this.eventType || '*')
linkObj || (linkObj = object{})
Fossil.extendProperties(this.linkProps, linkObj)
//linkObj.yearMonth = this.yearMonth
//linkObj.yearWeek = this.yearWeek
$out {<div class='reports-filter-type'>Event type filter:}
const linker = proc(k){
const v = typeMap.(k)
if('*'===k) { unset linkObj.type }
else { linkObj.type = k }
if(1){
if(k===currentEventType){
$out " <span class='active'>" v {</span>}
}else{
$out " <a href='?" CGI.objToUrlParams(linkObj) "'>" v {</a>}
}
}else{
$out " <a href='?" CGI.objToUrlParams(linkObj) "'"
(k===currentEventType) && $out " class='active'"
$out {>} v {</a>}
}
//return argv.callee
}
// bug: call chaining is not working here:
//linker({*})({ci})({t})({g})({wiki})
linker({*})
linker({ci})
linker({t})
linker({g})
linker({w})
linker({e})
$out {</div>}
}.importSymbols(nameof typeMap)
ns.generateLimitLinks = proc(){
const CGI = api.cgi
const out = CGI.out
const urlParams = Fossil.extendProperties(this.linkProps, object{
limit: +CGI.getVar('limit',0)
})
//print('urlparams =',urlParams)
const link = proc(n){
if(n !== urlParams.limit){
const old = urlParams.limit
urlParams.limit = n
//$out " <a href='?" CGI.objToUrlParams(urlParams) "'>" v {</a>}
$out ' ' CGI.html.createAnchor( '?' + CGI.objToUrlParams(urlParams), n )
urlParams.limit = old
}else{
$out " <span class='active'>" n {</span>}
}
}
$out {<div>Result limit:}
if(urlParams.limit){
const old = urlParams.limit
unset urlParams.limit
$out ' ' CGI.html.createAnchor( '?' + CGI.objToUrlParams(urlParams), 'default' )
urlParams.limit = old
}else{
$out ' ' {<span class='active'>default</span>}
}
//link(10)
link(20)
link(30)
link(50)
link(75)
link(100)
$out {</div>}
}
ns.generateRemoveUserLink = proc(params){
this.user || return
const out = api.io.output
params || (params = object{})
Fossil.extendProperties(this.linkProps, params)
unset params.user
params = api.cgi.objToUrlParams(params)
$out {<div>[<a href='?} params {'>Remove "user" filter</a>]</div>}
}
ns.generateSubmenu = proc(){
const CGI = api.cgi
const out = api.io.output
const obj = object {
'reports/by-user': 'User',
'reports/by-week': 'Week',
'reports/by-month': 'Month',
'reports/by-year': 'Year',
'timeline': 'Timeline'
}
var urlParams = object{
user: this.linkProps.user,
// CRASH: type: (('*'===this.eventType) ? undefined : this.eventType),
//type: this.eventType
year: this.linkProps.year
}
('*'===this.linkProps.type) || (urlParams.type = this.linkProps.type)
urlParams = CGI.objToUrlParams(urlParams)
var activePage
const PI = CGI.request.ENV.PATH_INFO
const reportLink = proc(name, label, tryMarkActive=true){
label || (label = obj.(name))
const isActive = tryMarkActive && (PI && (0<PI.indexOf(name)))
$out "<a href='" CGI.cgiRoot name
urlParams && $out {?} urlParams
$out "'"
if(isActive){
activePage = name
tryMarkActive && $out " class='active'"
}
$out ">" label '</a> '
}
$out {<div class='menu-sub'>Activity reports by:} ' '
reportLink('reports/by-year')
reportLink('reports/by-month')
reportLink('reports/by-week')
reportLink('reports/by-user')
reportLink('timeline')
if(activePage && CGI.request.GET){
urlParams = ''
reportLink(activePage, '[remove filters]', false)
}
$out {</div>}
}
ns.linkProps = object{}
return ns
}(object{})