| | @@ -132,10 +132,11 @@ |
| 132 | 132 | ** Allowed flags for the tmFlags argument to www_print_timeline |
| 133 | 133 | */ |
| 134 | 134 | #if INTERFACE |
| 135 | 135 | #define TIMELINE_ARTID 0x0001 /* Show artifact IDs on non-check-in lines */ |
| 136 | 136 | #define TIMELINE_LEAFONLY 0x0002 /* Show "Leaf", but not "Merge", "Fork" etc */ |
| 137 | +#define TIMELINE_BRIEF 0x0004 /* Combine adjacent elements of same object */ |
| 137 | 138 | #endif |
| 138 | 139 | |
| 139 | 140 | /* |
| 140 | 141 | ** Output a timeline in the web format given a query. The query |
| 141 | 142 | ** should return these columns: |
| | @@ -147,12 +148,14 @@ |
| 147 | 148 | ** 4. User |
| 148 | 149 | ** 5. Number of non-merge children |
| 149 | 150 | ** 6. Number of parents |
| 150 | 151 | ** 7. True if is a leaf |
| 151 | 152 | ** 8. background color |
| 152 | | -** 9. type ("ci", "w") |
| 153 | +** 9. type ("ci", "w", "t") |
| 153 | 154 | ** 10. list of symbolic tags. |
| 155 | +** 11. tagid for ticket or wiki |
| 156 | +** 12. Short comment to user for repeated tickets and wiki |
| 154 | 157 | */ |
| 155 | 158 | void www_print_timeline( |
| 156 | 159 | Stmt *pQuery, /* Query to implement the timeline */ |
| 157 | 160 | int tmFlags, /* Flags controlling display behavior */ |
| 158 | 161 | void (*xExtra)(int) /* Routine to call on each line of display */ |
| | @@ -160,10 +163,12 @@ |
| 160 | 163 | int wikiFlags; |
| 161 | 164 | int mxWikiLen; |
| 162 | 165 | Blob comment; |
| 163 | 166 | char zPrevDate[20]; |
| 164 | 167 | zPrevDate[0] = 0; |
| 168 | + int prevTagid = 0; |
| 169 | + int suppressCnt = 0; |
| 165 | 170 | |
| 166 | 171 | mxWikiLen = db_get_int("timeline-max-comment", 0); |
| 167 | 172 | if( db_get_boolean("timeline-block-markup", 0) ){ |
| 168 | 173 | wikiFlags = WIKI_INLINE; |
| 169 | 174 | }else{ |
| | @@ -185,10 +190,29 @@ |
| 185 | 190 | const char *zBgClr = db_column_text(pQuery, 8); |
| 186 | 191 | const char *zDate = db_column_text(pQuery, 2); |
| 187 | 192 | const char *zType = db_column_text(pQuery, 9); |
| 188 | 193 | const char *zUser = db_column_text(pQuery, 4); |
| 189 | 194 | const char *zTagList = db_column_text(pQuery, 10); |
| 195 | + int tagid = db_column_int(pQuery, 11); |
| 196 | + int commentColumn = 3; /* Column containing comment text */ |
| 197 | + if( tagid ){ |
| 198 | + if( tagid==prevTagid ){ |
| 199 | + if( tmFlags & TIMELINE_BRIEF ){ |
| 200 | + suppressCnt++; |
| 201 | + continue; |
| 202 | + }else{ |
| 203 | + commentColumn = 12; |
| 204 | + } |
| 205 | + } |
| 206 | + } |
| 207 | + prevTagid = tagid; |
| 208 | + if( suppressCnt ){ |
| 209 | + @ <tr><td><td><td> |
| 210 | + @ ... preceded by %d(suppressCnt) other |
| 211 | + @ similar event%s(suppressCnt>1?"s":"").</tr> |
| 212 | + suppressCnt = 0; |
| 213 | + } |
| 190 | 214 | if( strcmp(zType,"div")==0 ){ |
| 191 | 215 | @ <tr><td colspan=3><hr></td></tr> |
| 192 | 216 | continue; |
| 193 | 217 | } |
| 194 | 218 | db_multi_exec("INSERT OR IGNORE INTO seen VALUES(%d)", rid); |
| | @@ -239,11 +263,11 @@ |
| 239 | 263 | } |
| 240 | 264 | } |
| 241 | 265 | }else if( (tmFlags & TIMELINE_ARTID)!=0 ){ |
| 242 | 266 | hyperlink_to_uuid(zUuid); |
| 243 | 267 | } |
| 244 | | - db_column_blob(pQuery, 3, &comment); |
| 268 | + db_column_blob(pQuery, commentColumn, &comment); |
| 245 | 269 | if( mxWikiLen>0 && blob_size(&comment)>mxWikiLen ){ |
| 246 | 270 | Blob truncated; |
| 247 | 271 | blob_zero(&truncated); |
| 248 | 272 | blob_append(&truncated, blob_buffer(&comment), mxWikiLen); |
| 249 | 273 | blob_append(&truncated, "...", 3); |
| | @@ -280,11 +304,13 @@ |
| 280 | 304 | @ nchild INTEGER, |
| 281 | 305 | @ nparent INTEGER, |
| 282 | 306 | @ isleaf BOOLEAN, |
| 283 | 307 | @ bgcolor TEXT, |
| 284 | 308 | @ etype TEXT, |
| 285 | | - @ taglist TEXT |
| 309 | + @ taglist TEXT, |
| 310 | + @ tagid INTEGER, |
| 311 | + @ short TEXT |
| 286 | 312 | @ ) |
| 287 | 313 | ; |
| 288 | 314 | db_multi_exec(zSql); |
| 289 | 315 | } |
| 290 | 316 | |
| | @@ -311,11 +337,13 @@ |
| 311 | 337 | @ WHERE tagid=%d AND rid=plink.cid), 'trunk')), |
| 312 | 338 | @ bgcolor, |
| 313 | 339 | @ event.type, |
| 314 | 340 | @ (SELECT group_concat(substr(tagname,5), ', ') FROM tag, tagxref |
| 315 | 341 | @ WHERE tagname GLOB 'sym-*' AND tag.tagid=tagxref.tagid |
| 316 | | - @ AND tagxref.rid=blob.rid AND tagxref.tagtype>0) |
| 342 | + @ AND tagxref.rid=blob.rid AND tagxref.tagtype>0), |
| 343 | + @ tagid, |
| 344 | + @ brief |
| 317 | 345 | @ FROM event JOIN blob |
| 318 | 346 | @ WHERE blob.rid=event.objid |
| 319 | 347 | ; |
| 320 | 348 | if( zBase==0 ){ |
| 321 | 349 | zBase = mprintf(zBaseSql, TAG_BRANCH, TAG_BRANCH); |
| | @@ -393,19 +421,25 @@ |
| 393 | 421 | const char *zBefore = P("b"); /* Events before this time */ |
| 394 | 422 | const char *zCirca = P("c"); /* Events near this time */ |
| 395 | 423 | const char *zTagName = P("t"); /* Show events with this tag */ |
| 396 | 424 | HQuery url; /* URL for various branch links */ |
| 397 | 425 | int tagid; /* Tag ID */ |
| 426 | + int tmFlags; /* Timeline flags */ |
| 398 | 427 | |
| 399 | 428 | /* To view the timeline, must have permission to read project data. |
| 400 | 429 | */ |
| 401 | 430 | login_check_credentials(); |
| 402 | 431 | if( !g.okRead ){ login_needed(); return; } |
| 403 | 432 | if( zTagName ){ |
| 404 | 433 | tagid = db_int(0, "SELECT tagid FROM tag WHERE tagname='sym-%q'", zTagName); |
| 405 | 434 | }else{ |
| 406 | 435 | tagid = 0; |
| 436 | + } |
| 437 | + if( zType[0]=='a' ){ |
| 438 | + tmFlags = TIMELINE_BRIEF; |
| 439 | + }else{ |
| 440 | + tmFlags = 0; |
| 407 | 441 | } |
| 408 | 442 | |
| 409 | 443 | style_header("Timeline"); |
| 410 | 444 | login_anonymous_available(); |
| 411 | 445 | timeline_temp_table(); |
| | @@ -597,11 +631,11 @@ |
| 597 | 631 | } |
| 598 | 632 | blob_zero(&sql); |
| 599 | 633 | db_prepare(&q, "SELECT * FROM timeline ORDER BY timestamp DESC"); |
| 600 | 634 | @ <h2>%b(&desc)</h2> |
| 601 | 635 | blob_reset(&desc); |
| 602 | | - www_print_timeline(&q, 0, 0); |
| 636 | + www_print_timeline(&q, tmFlags, 0); |
| 603 | 637 | db_finalize(&q); |
| 604 | 638 | |
| 605 | 639 | @ <script> |
| 606 | 640 | @ var parentof = new Object(); |
| 607 | 641 | @ var childof = new Object(); |
| 608 | 642 | |