Fossil SCM

Improvements in the display of ticket history.

drh 2008-10-20 16:05 trunk
Commit c8a78004ce272d700f44890e7ce715a38afeac04
2 files changed +1 -32 +114 -6
+1 -32
--- src/info.c
+++ src/info.c
@@ -832,22 +832,10 @@
832832
@ </pre></blockquote>
833833
blob_reset(&content);
834834
style_footer();
835835
}
836836
837
-/*
838
-** Return TRUE if the given BLOB contains a newline character.
839
-*/
840
-static int contains_newline(Blob *p){
841
- const char *z = blob_str(p);
842
- while( *z ){
843
- if( *z=='\n' ) return 1;
844
- z++;
845
- }
846
- return 0;
847
-}
848
-
849837
/*
850838
** WEBPAGE: tinfo
851839
** URL: /tinfo?name=UUID
852840
**
853841
** Show the details of a ticket change control artifact.
@@ -854,14 +842,12 @@
854842
*/
855843
void tinfo_page(void){
856844
int rid;
857845
Blob content;
858846
char *zDate;
859
- int i;
860847
const char *zUuid;
861848
char zTktName[20];
862
- const char *z;
863849
Manifest m;
864850
865851
login_check_credentials();
866852
if( !g.okRdTkt ){ login_needed(); return; }
867853
rid = name_to_rid(PD("name","0"));
@@ -894,29 +880,12 @@
894880
@ <a href="%s(g.zTop)/tkthistory/%s(m.zTicketUuid)">ticket history</a>
895881
@ </p>
896882
@
897883
@ <ol>
898884
free(zDate);
899
- for(i=0; i<m.nField; i++){
900
- Blob val;
901
- z = m.aField[i].zName;
902
- blob_set(&val, m.aField[i].zValue);
903
- if( z[0]=='+' ){
904
- @ <li><p>Appended to %h(&z[1]):</p><blockquote>
905
- wiki_convert(&val, 0, 0);
906
- @ </blockquote></li>
907
- }else if( blob_size(&val)<=50 && contains_newline(&val) ){
908
- @ <li><p>Change %h(z) to:</p><blockquote>
909
- wiki_convert(&val, 0, 0);
910
- @ </blockquote></li>
911
- }else{
912
- @ <li><p>Change %h(z) to "%h(blob_str(&val))"</p></li>
913
- }
914
- blob_reset(&val);
915
- }
885
+ ticket_output_change_artifact(&m);
916886
manifest_clear(&m);
917
- @ </ol>
918887
style_footer();
919888
}
920889
921890
922891
/*
923892
--- src/info.c
+++ src/info.c
@@ -832,22 +832,10 @@
832 @ </pre></blockquote>
833 blob_reset(&content);
834 style_footer();
835 }
836
837 /*
838 ** Return TRUE if the given BLOB contains a newline character.
839 */
840 static int contains_newline(Blob *p){
841 const char *z = blob_str(p);
842 while( *z ){
843 if( *z=='\n' ) return 1;
844 z++;
845 }
846 return 0;
847 }
848
849 /*
850 ** WEBPAGE: tinfo
851 ** URL: /tinfo?name=UUID
852 **
853 ** Show the details of a ticket change control artifact.
@@ -854,14 +842,12 @@
854 */
855 void tinfo_page(void){
856 int rid;
857 Blob content;
858 char *zDate;
859 int i;
860 const char *zUuid;
861 char zTktName[20];
862 const char *z;
863 Manifest m;
864
865 login_check_credentials();
866 if( !g.okRdTkt ){ login_needed(); return; }
867 rid = name_to_rid(PD("name","0"));
@@ -894,29 +880,12 @@
894 @ <a href="%s(g.zTop)/tkthistory/%s(m.zTicketUuid)">ticket history</a>
895 @ </p>
896 @
897 @ <ol>
898 free(zDate);
899 for(i=0; i<m.nField; i++){
900 Blob val;
901 z = m.aField[i].zName;
902 blob_set(&val, m.aField[i].zValue);
903 if( z[0]=='+' ){
904 @ <li><p>Appended to %h(&z[1]):</p><blockquote>
905 wiki_convert(&val, 0, 0);
906 @ </blockquote></li>
907 }else if( blob_size(&val)<=50 && contains_newline(&val) ){
908 @ <li><p>Change %h(z) to:</p><blockquote>
909 wiki_convert(&val, 0, 0);
910 @ </blockquote></li>
911 }else{
912 @ <li><p>Change %h(z) to "%h(blob_str(&val))"</p></li>
913 }
914 blob_reset(&val);
915 }
916 manifest_clear(&m);
917 @ </ol>
918 style_footer();
919 }
920
921
922 /*
923
--- src/info.c
+++ src/info.c
@@ -832,22 +832,10 @@
832 @ </pre></blockquote>
833 blob_reset(&content);
834 style_footer();
835 }
836
 
 
 
 
 
 
 
 
 
 
 
 
837 /*
838 ** WEBPAGE: tinfo
839 ** URL: /tinfo?name=UUID
840 **
841 ** Show the details of a ticket change control artifact.
@@ -854,14 +842,12 @@
842 */
843 void tinfo_page(void){
844 int rid;
845 Blob content;
846 char *zDate;
 
847 const char *zUuid;
848 char zTktName[20];
 
849 Manifest m;
850
851 login_check_credentials();
852 if( !g.okRdTkt ){ login_needed(); return; }
853 rid = name_to_rid(PD("name","0"));
@@ -894,29 +880,12 @@
880 @ <a href="%s(g.zTop)/tkthistory/%s(m.zTicketUuid)">ticket history</a>
881 @ </p>
882 @
883 @ <ol>
884 free(zDate);
885 ticket_output_change_artifact(&m);
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
886 manifest_clear(&m);
 
887 style_footer();
888 }
889
890
891 /*
892
+114 -6
--- src/tkt.c
+++ src/tkt.c
@@ -323,12 +323,15 @@
323323
if( g.okWrTkt ){
324324
style_submenu_element("Edit", "Edit The Ticket", "%s/tktedit?name=%T",
325325
g.zTop, PD("name",""));
326326
}
327327
if( g.okHistory ){
328
+ const char *zUuid = PD("name","");
328329
style_submenu_element("History", "History Of This Ticket",
329
- "%s/tkthistory/%T", g.zTop, PD("name",""));
330
+ "%s/tkthistory/%T", g.zTop, zUuid);
331
+ style_submenu_element("Timeline", "Timeline Of This Ticket",
332
+ "%s/tkttimeline/%T", g.zTop, zUuid);
330333
}
331334
style_header("View Ticket");
332335
ticket_init();
333336
initializeVariablesFromDb();
334337
zScript = ticket_viewpage_code();
@@ -580,26 +583,30 @@
580583
}
581584
return 0;
582585
}
583586
584587
/*
585
-** WEBPAGE: tkthistory
586
-** URL: /tkthistory?name=TICKETUUID
588
+** WEBPAGE: tkttimeline
589
+** URL: /tkttimeline?name=TICKETUUID
587590
**
588
-** Show the complete change history for a single ticket
591
+** Show the change history for a single ticket in timeline format.
589592
*/
590
-void tkthistory_page(void){
593
+void tkttimeline_page(void){
591594
Stmt q;
592595
char *zTitle;
593596
char *zSQL;
594597
const char *zUuid;
595598
int tagid;
596599
597600
login_check_credentials();
598601
if( !g.okHistory || !g.okRdTkt ){ login_needed(); return; }
599602
zUuid = PD("name","");
600
- zTitle = mprintf("History Of Ticket %h", zUuid);
603
+ style_submenu_element("History", "History",
604
+ "%s/tkthistory/%s", g.zTop, zUuid);
605
+ style_submenu_element("Status", "Status",
606
+ "%s/info/%s", g.zTop, zUuid);
607
+ zTitle = mprintf("Timeline Of Ticket %h", zUuid);
601608
style_header(zTitle);
602609
free(zTitle);
603610
604611
tagid = db_int(0, "SELECT tagid FROM tag WHERE tagname GLOB 'tkt-%q*'",zUuid);
605612
if( tagid==0 ){
@@ -615,5 +622,106 @@
615622
free(zSQL);
616623
www_print_timeline(&q);
617624
db_finalize(&q);
618625
style_footer();
619626
}
627
+
628
+/*
629
+** WEBPAGE: tkthistory
630
+** URL: /tkthistory?name=TICKETUUID
631
+**
632
+** Show the complete change history for a single ticket
633
+*/
634
+void tkthistory_page(void){
635
+ Stmt q;
636
+ char *zTitle;
637
+ const char *zUuid;
638
+ int tagid;
639
+
640
+ login_check_credentials();
641
+ if( !g.okHistory || !g.okRdTkt ){ login_needed(); return; }
642
+ zUuid = PD("name","");
643
+ zTitle = mprintf("History Of Ticket %h", zUuid);
644
+ style_submenu_element("Status", "Status",
645
+ "%s/info/%s", g.zTop, zUuid);
646
+ style_submenu_element("Timeline", "Timeline",
647
+ "%s/tkttimeline?name=%s", g.zTop, zUuid);
648
+ style_header(zTitle);
649
+ free(zTitle);
650
+
651
+ tagid = db_int(0, "SELECT tagid FROM tag WHERE tagname GLOB 'tkt-%q*'",zUuid);
652
+ if( tagid==0 ){
653
+ @ No such ticket: %h(zUuid)
654
+ style_footer();
655
+ return;
656
+ }
657
+ db_prepare(&q,
658
+ "SELECT objid, uuid FROM event, blob"
659
+ " WHERE objid IN (SELECT rid FROM tagxref WHERE tagid=%d)"
660
+ " AND blob.rid=event.objid"
661
+ " ORDER BY mtime DESC",
662
+ tagid
663
+ );
664
+ while( db_step(&q)==SQLITE_ROW ){
665
+ Blob content;
666
+ Manifest m;
667
+ int rid = db_column_int(&q, 0);
668
+ const char *zChngUuid = db_column_text(&q, 1);
669
+ content_get(rid, &content);
670
+ if( manifest_parse(&m, &content) && m.type==CFTYPE_TICKET ){
671
+ char *zDate = db_text(0, "SELECT datetime(%.12f)", m.rDate);
672
+ char zUuid[12];
673
+ memcpy(zUuid, zChngUuid, 10);
674
+ zUuid[10] = 0;
675
+ @
676
+ @ <p>%s(zDate)
677
+ @ [<a href="%s(g.zTop)/artifact/%T(zChngUuid)">%s(zUuid)</a>]</a>
678
+ @ by %h(m.zUser):</p>
679
+ @
680
+ free(zDate);
681
+ ticket_output_change_artifact(&m);
682
+ }
683
+ manifest_clear(&m);
684
+ }
685
+ db_finalize(&q);
686
+ style_footer();
687
+}
688
+
689
+/*
690
+** Return TRUE if the given BLOB contains a newline character.
691
+*/
692
+static int contains_newline(Blob *p){
693
+ const char *z = blob_str(p);
694
+ while( *z ){
695
+ if( *z=='\n' ) return 1;
696
+ z++;
697
+ }
698
+ return 0;
699
+}
700
+
701
+/*
702
+** The pTkt object is a ticket change artifact. Output a detailed
703
+** description of this object.
704
+*/
705
+void ticket_output_change_artifact(Manifest *pTkt){
706
+ int i;
707
+ @ <ol>
708
+ for(i=0; i<pTkt->nField; i++){
709
+ Blob val;
710
+ const char *z;
711
+ z = pTkt->aField[i].zName;
712
+ blob_set(&val, pTkt->aField[i].zValue);
713
+ if( z[0]=='+' ){
714
+ @ <li>Appended to %h(&z[1]):<blockquote>
715
+ wiki_convert(&val, 0, 0);
716
+ @ </blockquote></li>
717
+ }else if( blob_size(&val)<=50 && contains_newline(&val) ){
718
+ @ <li>Change %h(z) to:<blockquote>
719
+ wiki_convert(&val, 0, 0);
720
+ @ </blockquote></li>
721
+ }else{
722
+ @ <li>Change %h(z) to "%h(blob_str(&val))"</li>
723
+ }
724
+ blob_reset(&val);
725
+ }
726
+ @ </ol>
727
+}
620728
--- src/tkt.c
+++ src/tkt.c
@@ -323,12 +323,15 @@
323 if( g.okWrTkt ){
324 style_submenu_element("Edit", "Edit The Ticket", "%s/tktedit?name=%T",
325 g.zTop, PD("name",""));
326 }
327 if( g.okHistory ){
 
328 style_submenu_element("History", "History Of This Ticket",
329 "%s/tkthistory/%T", g.zTop, PD("name",""));
 
 
330 }
331 style_header("View Ticket");
332 ticket_init();
333 initializeVariablesFromDb();
334 zScript = ticket_viewpage_code();
@@ -580,26 +583,30 @@
580 }
581 return 0;
582 }
583
584 /*
585 ** WEBPAGE: tkthistory
586 ** URL: /tkthistory?name=TICKETUUID
587 **
588 ** Show the complete change history for a single ticket
589 */
590 void tkthistory_page(void){
591 Stmt q;
592 char *zTitle;
593 char *zSQL;
594 const char *zUuid;
595 int tagid;
596
597 login_check_credentials();
598 if( !g.okHistory || !g.okRdTkt ){ login_needed(); return; }
599 zUuid = PD("name","");
600 zTitle = mprintf("History Of Ticket %h", zUuid);
 
 
 
 
601 style_header(zTitle);
602 free(zTitle);
603
604 tagid = db_int(0, "SELECT tagid FROM tag WHERE tagname GLOB 'tkt-%q*'",zUuid);
605 if( tagid==0 ){
@@ -615,5 +622,106 @@
615 free(zSQL);
616 www_print_timeline(&q);
617 db_finalize(&q);
618 style_footer();
619 }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
620
--- src/tkt.c
+++ src/tkt.c
@@ -323,12 +323,15 @@
323 if( g.okWrTkt ){
324 style_submenu_element("Edit", "Edit The Ticket", "%s/tktedit?name=%T",
325 g.zTop, PD("name",""));
326 }
327 if( g.okHistory ){
328 const char *zUuid = PD("name","");
329 style_submenu_element("History", "History Of This Ticket",
330 "%s/tkthistory/%T", g.zTop, zUuid);
331 style_submenu_element("Timeline", "Timeline Of This Ticket",
332 "%s/tkttimeline/%T", g.zTop, zUuid);
333 }
334 style_header("View Ticket");
335 ticket_init();
336 initializeVariablesFromDb();
337 zScript = ticket_viewpage_code();
@@ -580,26 +583,30 @@
583 }
584 return 0;
585 }
586
587 /*
588 ** WEBPAGE: tkttimeline
589 ** URL: /tkttimeline?name=TICKETUUID
590 **
591 ** Show the change history for a single ticket in timeline format.
592 */
593 void tkttimeline_page(void){
594 Stmt q;
595 char *zTitle;
596 char *zSQL;
597 const char *zUuid;
598 int tagid;
599
600 login_check_credentials();
601 if( !g.okHistory || !g.okRdTkt ){ login_needed(); return; }
602 zUuid = PD("name","");
603 style_submenu_element("History", "History",
604 "%s/tkthistory/%s", g.zTop, zUuid);
605 style_submenu_element("Status", "Status",
606 "%s/info/%s", g.zTop, zUuid);
607 zTitle = mprintf("Timeline Of Ticket %h", zUuid);
608 style_header(zTitle);
609 free(zTitle);
610
611 tagid = db_int(0, "SELECT tagid FROM tag WHERE tagname GLOB 'tkt-%q*'",zUuid);
612 if( tagid==0 ){
@@ -615,5 +622,106 @@
622 free(zSQL);
623 www_print_timeline(&q);
624 db_finalize(&q);
625 style_footer();
626 }
627
628 /*
629 ** WEBPAGE: tkthistory
630 ** URL: /tkthistory?name=TICKETUUID
631 **
632 ** Show the complete change history for a single ticket
633 */
634 void tkthistory_page(void){
635 Stmt q;
636 char *zTitle;
637 const char *zUuid;
638 int tagid;
639
640 login_check_credentials();
641 if( !g.okHistory || !g.okRdTkt ){ login_needed(); return; }
642 zUuid = PD("name","");
643 zTitle = mprintf("History Of Ticket %h", zUuid);
644 style_submenu_element("Status", "Status",
645 "%s/info/%s", g.zTop, zUuid);
646 style_submenu_element("Timeline", "Timeline",
647 "%s/tkttimeline?name=%s", g.zTop, zUuid);
648 style_header(zTitle);
649 free(zTitle);
650
651 tagid = db_int(0, "SELECT tagid FROM tag WHERE tagname GLOB 'tkt-%q*'",zUuid);
652 if( tagid==0 ){
653 @ No such ticket: %h(zUuid)
654 style_footer();
655 return;
656 }
657 db_prepare(&q,
658 "SELECT objid, uuid FROM event, blob"
659 " WHERE objid IN (SELECT rid FROM tagxref WHERE tagid=%d)"
660 " AND blob.rid=event.objid"
661 " ORDER BY mtime DESC",
662 tagid
663 );
664 while( db_step(&q)==SQLITE_ROW ){
665 Blob content;
666 Manifest m;
667 int rid = db_column_int(&q, 0);
668 const char *zChngUuid = db_column_text(&q, 1);
669 content_get(rid, &content);
670 if( manifest_parse(&m, &content) && m.type==CFTYPE_TICKET ){
671 char *zDate = db_text(0, "SELECT datetime(%.12f)", m.rDate);
672 char zUuid[12];
673 memcpy(zUuid, zChngUuid, 10);
674 zUuid[10] = 0;
675 @
676 @ <p>%s(zDate)
677 @ [<a href="%s(g.zTop)/artifact/%T(zChngUuid)">%s(zUuid)</a>]</a>
678 @ by %h(m.zUser):</p>
679 @
680 free(zDate);
681 ticket_output_change_artifact(&m);
682 }
683 manifest_clear(&m);
684 }
685 db_finalize(&q);
686 style_footer();
687 }
688
689 /*
690 ** Return TRUE if the given BLOB contains a newline character.
691 */
692 static int contains_newline(Blob *p){
693 const char *z = blob_str(p);
694 while( *z ){
695 if( *z=='\n' ) return 1;
696 z++;
697 }
698 return 0;
699 }
700
701 /*
702 ** The pTkt object is a ticket change artifact. Output a detailed
703 ** description of this object.
704 */
705 void ticket_output_change_artifact(Manifest *pTkt){
706 int i;
707 @ <ol>
708 for(i=0; i<pTkt->nField; i++){
709 Blob val;
710 const char *z;
711 z = pTkt->aField[i].zName;
712 blob_set(&val, pTkt->aField[i].zValue);
713 if( z[0]=='+' ){
714 @ <li>Appended to %h(&z[1]):<blockquote>
715 wiki_convert(&val, 0, 0);
716 @ </blockquote></li>
717 }else if( blob_size(&val)<=50 && contains_newline(&val) ){
718 @ <li>Change %h(z) to:<blockquote>
719 wiki_convert(&val, 0, 0);
720 @ </blockquote></li>
721 }else{
722 @ <li>Change %h(z) to "%h(blob_str(&val))"</li>
723 }
724 blob_reset(&val);
725 }
726 @ </ol>
727 }
728

Keyboard Shortcuts

Open search /
Next entry (timeline) j
Previous entry (timeline) k
Open focused entry Enter
Show this help ?
Toggle theme Top nav button