| | @@ -75,11 +75,11 @@ |
| 75 | 75 | } |
| 76 | 76 | } |
| 77 | 77 | |
| 78 | 78 | /* |
| 79 | 79 | ** Output a timeline in the web format given a query. The query |
| 80 | | -** should return 4 columns: |
| 80 | +** should return these columns: |
| 81 | 81 | ** |
| 82 | 82 | ** 0. rid |
| 83 | 83 | ** 1. UUID |
| 84 | 84 | ** 2. Date/Time |
| 85 | 85 | ** 3. Comment string |
| | @@ -187,10 +187,44 @@ |
| 187 | 187 | } |
| 188 | 188 | db_finalize(&q); |
| 189 | 189 | blob_appendf(pOut, "];\n"); |
| 190 | 190 | return 0; |
| 191 | 191 | } |
| 192 | + |
| 193 | +/* |
| 194 | +** Return a pointer to a constant string that forms the basis |
| 195 | +** for a timeline query for the WWW interface. |
| 196 | +*/ |
| 197 | +const char *timeline_query_for_www(void){ |
| 198 | + static const char zBaseSql[] = |
| 199 | + @ SELECT |
| 200 | + @ blob.rid, |
| 201 | + @ uuid, |
| 202 | + @ datetime(event.mtime,'localtime'), |
| 203 | + @ coalesce((SELECT value FROM tagxref |
| 204 | + @ WHERE rid=blob.rid |
| 205 | + @ AND tagid=(SELECT tagid FROM tag WHERE tagname='comment')), |
| 206 | + @ comment), |
| 207 | + @ coalesce((SELECT value FROM tagxref |
| 208 | + @ WHERE rid=blob.rid |
| 209 | + @ AND tagid=(SELECT tagid FROM tag WHERE tagname='user')), |
| 210 | + @ user), |
| 211 | + @ (SELECT count(*) FROM plink WHERE pid=blob.rid AND isprim=1), |
| 212 | + @ (SELECT count(*) FROM plink WHERE cid=blob.rid), |
| 213 | + @ NOT EXISTS (SELECT 1 FROM plink WHERE pid=blob.rid), |
| 214 | + @ (SELECT value FROM tagxref |
| 215 | + @ WHERE rid=blob.rid |
| 216 | + @ AND tagid=(SELECT tagid FROM tag WHERE tagname='bgcolor') |
| 217 | + @ UNION ALL |
| 218 | + @ SELECT value FROM tagxref |
| 219 | + @ WHERE rid=blob.rid |
| 220 | + @ AND tagid=(SELECT tagid FROM tag WHERE tagname='br-bgcolor')) |
| 221 | + @ FROM event JOIN blob |
| 222 | + @ WHERE blob.rid=event.objid |
| 223 | + ; |
| 224 | + return zBaseSql; |
| 225 | +} |
| 192 | 226 | |
| 193 | 227 | /* |
| 194 | 228 | ** WEBPAGE: timeline |
| 195 | 229 | ** |
| 196 | 230 | ** Query parameters: |
| | @@ -213,38 +247,25 @@ |
| 213 | 247 | int objid = atoi(PD("e","0")); |
| 214 | 248 | int relatedEvents = P("r")!=0; |
| 215 | 249 | int afterFlag = P("a")!=0; |
| 216 | 250 | int firstEvent; |
| 217 | 251 | int lastEvent; |
| 218 | | - int clr1, clr2; /* Tag IDs for specifying background colors */ |
| 219 | 252 | |
| 220 | 253 | /* To view the timeline, must have permission to read project data. |
| 221 | 254 | */ |
| 222 | 255 | login_check_credentials(); |
| 223 | 256 | if( !g.okRead ){ login_needed(); return; } |
| 224 | 257 | |
| 225 | 258 | style_header("Timeline"); |
| 226 | | - clr1 = db_int(0, "SELECT tagid FROM tag WHERE tagname='br-bg-color'"); |
| 227 | | - clr2 = db_int(0, "SELECT tagid FROM tag WHERE tagname='bg-color'"); |
| 228 | 259 | if( !g.okHistory && |
| 229 | 260 | db_exists("SELECT 1 FROM user" |
| 230 | 261 | " WHERE login='anonymous'" |
| 231 | 262 | " AND cap LIKE '%%h%%'") ){ |
| 232 | 263 | @ <p><b>Note:</b> You will be able to access <u>much</u> more |
| 233 | 264 | @ historical information if <a href="%s(g.zBaseURL)/login">login</a>.</p> |
| 234 | 265 | } |
| 235 | | - zSQL = mprintf( |
| 236 | | - "SELECT blob.rid, uuid, datetime(event.mtime,'localtime'), comment, user," |
| 237 | | - " (SELECT count(*) FROM plink WHERE pid=blob.rid AND isprim=1)," |
| 238 | | - " (SELECT count(*) FROM plink WHERE cid=blob.rid)," |
| 239 | | - " NOT EXISTS (SELECT 1 FROM plink WHERE pid=blob.rid)," |
| 240 | | - " (SELECT value FROM tagxref WHERE rid=blob.rid AND tagid=%d" |
| 241 | | - " UNION ALL" |
| 242 | | - " SELECT value FROM tagxref WHERE rid=blob.rid AND tagid=%d)" |
| 243 | | - " FROM event JOIN blob" |
| 244 | | - " WHERE event.type='ci' AND blob.rid=event.objid", clr2, clr1 |
| 245 | | - ); |
| 266 | + zSQL = mprintf("%s", timeline_query_for_www()); |
| 246 | 267 | if( zUser ){ |
| 247 | 268 | zSQL = mprintf("%z AND event.user=%Q", zSQL, zUser); |
| 248 | 269 | } |
| 249 | 270 | if( objid ){ |
| 250 | 271 | char *z = db_text(0, "SELECT datetime(event.mtime) FROM event" |
| | @@ -367,10 +388,19 @@ |
| 367 | 388 | /* |
| 368 | 389 | ** The input query q selects various records. Print a human-readable |
| 369 | 390 | ** summary of those records. |
| 370 | 391 | ** |
| 371 | 392 | ** Limit the number of entries printed to nLine. |
| 393 | +** |
| 394 | +** The query should return these columns: |
| 395 | +** |
| 396 | +** 0. rid |
| 397 | +** 1. uuid |
| 398 | +** 2. Date/Time |
| 399 | +** 3. Comment string and user |
| 400 | +** 4. Number of non-merge children |
| 401 | +** 5. Number of parents |
| 372 | 402 | */ |
| 373 | 403 | void print_timeline(Stmt *q, int mxLine){ |
| 374 | 404 | int nLine = 0; |
| 375 | 405 | char zPrevDate[20]; |
| 376 | 406 | zPrevDate[0] = 0; |
| | @@ -409,10 +439,38 @@ |
| 409 | 439 | } |
| 410 | 440 | nLine += comment_print(zFree, 9, 79); |
| 411 | 441 | sqlite3_free(zFree); |
| 412 | 442 | } |
| 413 | 443 | } |
| 444 | + |
| 445 | +/* |
| 446 | +** Return a pointer to a static string that forms the basis for |
| 447 | +** a timeline query for display on a TTY. |
| 448 | +*/ |
| 449 | +const char *timeline_query_for_tty(void){ |
| 450 | + static const char zBaseSql[] = |
| 451 | + @ SELECT |
| 452 | + @ blob.rid, |
| 453 | + @ uuid, |
| 454 | + @ datetime(event.mtime,'localtime'), |
| 455 | + @ coalesce((SELECT value FROM tagxref |
| 456 | + @ WHERE rid=blob.rid |
| 457 | + @ AND tagid=(SELECT tagid FROM tag WHERE tagname='comment')), |
| 458 | + @ comment) |
| 459 | + @ || ' (by ' || |
| 460 | + @ coalesce((SELECT value FROM tagxref |
| 461 | + @ WHERE rid=blob.rid |
| 462 | + @ AND tagid=(SELECT tagid FROM tag WHERE tagname='user')), |
| 463 | + @ user) |
| 464 | + @ || ')', |
| 465 | + @ (SELECT count(*) FROM plink WHERE pid=blob.rid AND isprim), |
| 466 | + @ (SELECT count(*) FROM plink WHERE cid=blob.rid) |
| 467 | + @ FROM event, blob |
| 468 | + @ WHERE blob.rid=event.objid |
| 469 | + ; |
| 470 | + return zBaseSql; |
| 471 | +} |
| 414 | 472 | |
| 415 | 473 | |
| 416 | 474 | /* |
| 417 | 475 | ** COMMAND: timeline |
| 418 | 476 | ** |
| | @@ -492,19 +550,14 @@ |
| 492 | 550 | if( mode==3 || mode==4 ){ |
| 493 | 551 | fossil_fatal("cannot compute descendents or ancestors of a date"); |
| 494 | 552 | } |
| 495 | 553 | zDate = mprintf("(SELECT julianday(%Q, 'utc'))", zOrigin); |
| 496 | 554 | } |
| 497 | | - zSQL = mprintf( |
| 498 | | - "SELECT blob.rid, uuid, datetime(event.mtime,'localtime')," |
| 499 | | - " comment || ' (by ' || user || ')'," |
| 500 | | - " (SELECT count(*) FROM plink WHERE pid=blob.rid AND isprim)," |
| 501 | | - " (SELECT count(*) FROM plink WHERE cid=blob.rid)" |
| 502 | | - " FROM event, blob" |
| 503 | | - " WHERE event.type='ci' AND blob.rid=event.objid" |
| 504 | | - " AND event.mtime %s %s", |
| 505 | | - (mode==1 || mode==4) ? "<=" : ">=", zDate |
| 555 | + zSQL = mprintf("%s AND event.mtime %s %s", |
| 556 | + timeline_query_for_tty(), |
| 557 | + (mode==1 || mode==4) ? "<=" : ">=", |
| 558 | + zDate |
| 506 | 559 | ); |
| 507 | 560 | if( mode==3 || mode==4 ){ |
| 508 | 561 | db_multi_exec("CREATE TEMP TABLE ok(rid INTEGER PRIMARY KEY)"); |
| 509 | 562 | if( mode==3 ){ |
| 510 | 563 | compute_descendents(objid, n); |
| 511 | 564 | |