Fossil

Check-in [3d131528c8]
Login

Check-in [3d131528c8]

Many hyperlinks are disabled.
Use anonymous login to enable hyperlinks.

Overview
Comment:Add a timeline view at the top of the /tktview page if the "tl" query parameter is present. If a ticket is viewed from /info, then the timeline is always on. Perhaps the timeline should be on regardless?
Downloads: Tarball | ZIP archive
Timelines: family | ancestors | descendants | both | trunk
Files: files | file ages | folders
SHA3-256: 3d131528c8c0167d6d1d06cd161e752d6c2ae53d03e56909635f4ab6259a6162
User & Date: drh 2019-12-23 12:26:03.811
Context
2019-12-23
12:38
Add the "New Ticket" option to timeline displays. ... (check-in: 9bb70584a1 user: drh tags: trunk)
12:26
Add a timeline view at the top of the /tktview page if the "tl" query parameter is present. If a ticket is viewed from /info, then the timeline is always on. Perhaps the timeline should be on regardless? ... (check-in: 3d131528c8 user: drh tags: trunk)
02:08
Merged in memleak-fixes brach. This fixes several genuine leaks, including 2 in manifest parsing, and cleans up the large work caches during atexit() in order to (A) separate that valgrind noise from the real leaks and (B) leave a better impression on those running valgrind. ... (check-in: 4cf8dbe398 user: stephan tags: trunk)
Changes
Unified Diff Ignore Whitespace Patch
Changes to src/info.c.
2509
2510
2511
2512
2513
2514
2515

2516
2517
2518
2519
2520
2521
2522
    ambiguous_page();
    return;
  }
  rc = name_to_uuid(&uuid, -1, "*");
  if( rc==1 ){
    if( validate16(zName, nLen) ){
      if( db_exists("SELECT 1 FROM ticket WHERE tkt_uuid GLOB '%q*'", zName) ){

        tktview_page();
        return;
      }
      if( db_exists("SELECT 1 FROM tag"
                    " WHERE tagname GLOB 'event-%q*'", zName) ){
        event_page();
        return;







>







2509
2510
2511
2512
2513
2514
2515
2516
2517
2518
2519
2520
2521
2522
2523
    ambiguous_page();
    return;
  }
  rc = name_to_uuid(&uuid, -1, "*");
  if( rc==1 ){
    if( validate16(zName, nLen) ){
      if( db_exists("SELECT 1 FROM ticket WHERE tkt_uuid GLOB '%q*'", zName) ){
        cgi_set_parameter_nocopy("tl","1",0);
        tktview_page();
        return;
      }
      if( db_exists("SELECT 1 FROM tag"
                    " WHERE tagname GLOB 'event-%q*'", zName) ){
        event_page();
        return;
Changes to src/tkt.c.
443
444
445
446
447
448
449
450
451
452



453
454
455
456
457

458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481













482
483
484
485
486
487
488
    @ mUsed = %d(aField[i].mUsed);
  }
  @ </ul></div>
}

/*
** WEBPAGE: tktview
** URL:  tktview?name=UUID
**
** View a ticket identified by the name= query parameter.



*/
void tktview_page(void){
  const char *zScript;
  char *zFullName;
  const char *zUuid = PD("name","");


  login_check_credentials();
  if( !g.perm.RdTkt ){ login_needed(g.anon.RdTkt); return; }
  if( g.anon.WrTkt || g.anon.ApndTkt ){
    style_submenu_element("Edit", "%s/tktedit?name=%T", g.zTop, PD("name",""));
  }
  if( g.perm.Hyperlink ){
    style_submenu_element("History", "%s/tkthistory/%T", g.zTop, zUuid);
    style_submenu_element("Timeline", "%s/tkttimeline/%T", g.zTop, zUuid);
    style_submenu_element("Check-ins", "%s/tkttimeline/%T?y=ci", g.zTop, zUuid);
  }
  if( g.anon.NewTkt ){
    style_submenu_element("New Ticket", "%s/tktnew", g.zTop);
  }
  if( g.anon.ApndTkt && g.anon.Attach ){
    style_submenu_element("Attach", "%s/attachadd?tkt=%T&from=%s/tktview/%t",
        g.zTop, zUuid, g.zTop, zUuid);
  }
  if( P("plaintext") ){
    style_submenu_element("Formatted", "%R/tktview/%s", zUuid);
  }else{
    style_submenu_element("Plaintext", "%R/tktview/%s?plaintext", zUuid);
  }
  style_header("View Ticket");













  if( g.thTrace ) Th_Trace("BEGIN_TKTVIEW<br />\n", -1);
  ticket_init();
  initializeVariablesFromCGI();
  getAllTicketFields();
  initializeVariablesFromDb();
  zScript = ticket_viewpage_code();
  if( P("showfields")!=0 ) showAllFields();







|


>
>
>





>








<















>
>
>
>
>
>
>
>
>
>
>
>
>







443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469

470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
    @ mUsed = %d(aField[i].mUsed);
  }
  @ </ul></div>
}

/*
** WEBPAGE: tktview
** URL:  tktview?name=HASH
**
** View a ticket identified by the name= query parameter.
** Other query parameters:
**
**      tl               Show a timeline of the ticket above the status
*/
void tktview_page(void){
  const char *zScript;
  char *zFullName;
  const char *zUuid = PD("name","");
  int showTimeline = P("tl")!=0;

  login_check_credentials();
  if( !g.perm.RdTkt ){ login_needed(g.anon.RdTkt); return; }
  if( g.anon.WrTkt || g.anon.ApndTkt ){
    style_submenu_element("Edit", "%s/tktedit?name=%T", g.zTop, PD("name",""));
  }
  if( g.perm.Hyperlink ){
    style_submenu_element("History", "%s/tkthistory/%T", g.zTop, zUuid);

    style_submenu_element("Check-ins", "%s/tkttimeline/%T?y=ci", g.zTop, zUuid);
  }
  if( g.anon.NewTkt ){
    style_submenu_element("New Ticket", "%s/tktnew", g.zTop);
  }
  if( g.anon.ApndTkt && g.anon.Attach ){
    style_submenu_element("Attach", "%s/attachadd?tkt=%T&from=%s/tktview/%t",
        g.zTop, zUuid, g.zTop, zUuid);
  }
  if( P("plaintext") ){
    style_submenu_element("Formatted", "%R/tktview/%s", zUuid);
  }else{
    style_submenu_element("Plaintext", "%R/tktview/%s?plaintext", zUuid);
  }
  style_header("View Ticket");
  if( showTimeline ){
    int tagid = db_int(0,"SELECT tagid FROM tag WHERE tagname GLOB 'tkt-%q*'",
                       zUuid);
    if( tagid ){
      tkt_draw_timeline(tagid, "a");
      @ <hr>
    }else{
      showTimeline = 0;
    }
  }
  if( !showTimeline && g.perm.Hyperlink ){
    style_submenu_element("Timeline", "%s/info/%T", g.zTop, zUuid);
  }
  if( g.thTrace ) Th_Trace("BEGIN_TKTVIEW<br />\n", -1);
  ticket_init();
  initializeVariablesFromCGI();
  getAllTicketFields();
  initializeVariablesFromDb();
  zScript = ticket_viewpage_code();
  if( P("showfields")!=0 ) showAllFields();
823
824
825
826
827
828
829






































830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
                       "table containing all required fields");
      }
    }
    sqlite3_close(db);
  }
  return zErr;
}







































/*
** WEBPAGE: tkttimeline
** URL: /tkttimeline?name=TICKETUUID&y=TYPE
**
** Show the change history for a single ticket in timeline format.
*/
void tkttimeline_page(void){
  Stmt q;
  char *zTitle;
  char *zSQL;
  const char *zUuid;
  char *zFullUuid;
  int tagid;
  char zGlobPattern[50];
  const char *zType;

  login_check_credentials();
  if( !g.perm.Hyperlink || !g.perm.RdTkt ){
    login_needed(g.anon.Hyperlink && g.anon.RdTkt);







>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>








<

<

<







839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891

892

893

894
895
896
897
898
899
900
                       "table containing all required fields");
      }
    }
    sqlite3_close(db);
  }
  return zErr;
}

/*
** Draw a timeline for a ticket with tag.tagid given by the tagid
** parameter.
*/
void tkt_draw_timeline(int tagid, const char *zType){
  Stmt q;
  char *zFullUuid;
  char *zSQL;
  zFullUuid = db_text(0, "SELECT substr(tagname, 5) FROM tag WHERE tagid=%d",
                         tagid);
  if( zType[0]=='c' ){
    zSQL = mprintf(
         "%s AND event.objid IN "
         "   (SELECT srcid FROM backlink WHERE target GLOB '%.4s*' "
                                         "AND '%s' GLOB (target||'*')) "
         "ORDER BY mtime DESC",
         timeline_query_for_www(), zFullUuid, zFullUuid
    );
  }else{
    zSQL = mprintf(
         "%s AND event.objid IN "
         "  (SELECT rid FROM tagxref WHERE tagid=%d"
         "   UNION SELECT srcid FROM backlink"
                  " WHERE target GLOB '%.4s*'"
                  "   AND '%s' GLOB (target||'*')"
         "   UNION SELECT attachid FROM attachment"
                  " WHERE target=%Q) "
         "ORDER BY mtime DESC",
         timeline_query_for_www(), tagid, zFullUuid, zFullUuid, zFullUuid
    );
  }
  db_prepare(&q, "%z", zSQL/*safe-for-%s*/);
  www_print_timeline(&q, TIMELINE_ARTID|TIMELINE_DISJOINT|TIMELINE_GRAPH,
                     0, 0, 0, 0, 0, 0);
  db_finalize(&q);
  fossil_free(zFullUuid);
}

/*
** WEBPAGE: tkttimeline
** URL: /tkttimeline?name=TICKETUUID&y=TYPE
**
** Show the change history for a single ticket in timeline format.
*/
void tkttimeline_page(void){

  char *zTitle;

  const char *zUuid;

  int tagid;
  char zGlobPattern[50];
  const char *zType;

  login_check_credentials();
  if( !g.perm.Hyperlink || !g.perm.RdTkt ){
    login_needed(g.anon.Hyperlink && g.anon.RdTkt);
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
  canonical16(zGlobPattern, strlen(zGlobPattern));
  tagid = db_int(0, "SELECT tagid FROM tag WHERE tagname GLOB 'tkt-%q*'",zUuid);
  if( tagid==0 ){
    @ No such ticket: %h(zUuid)
    style_footer();
    return;
  }
  zFullUuid = db_text(0, "SELECT substr(tagname, 5) FROM tag WHERE tagid=%d",
                         tagid);
  if( zType[0]=='c' ){
    zSQL = mprintf(
         "%s AND event.objid IN "
         "   (SELECT srcid FROM backlink WHERE target GLOB '%.4s*' "
                                         "AND '%s' GLOB (target||'*')) "
         "ORDER BY mtime DESC",
         timeline_query_for_www(), zFullUuid, zFullUuid
    );
  }else{
    zSQL = mprintf(
         "%s AND event.objid IN "
         "  (SELECT rid FROM tagxref WHERE tagid=%d"
         "   UNION SELECT srcid FROM backlink"
                  " WHERE target GLOB '%.4s*'"
                  "   AND '%s' GLOB (target||'*')"
         "   UNION SELECT attachid FROM attachment"
                  " WHERE target=%Q) "
         "ORDER BY mtime DESC",
         timeline_query_for_www(), tagid, zFullUuid, zFullUuid, zFullUuid
    );
  }
  db_prepare(&q, "%z", zSQL/*safe-for-%s*/);
  www_print_timeline(&q, TIMELINE_ARTID|TIMELINE_DISJOINT|TIMELINE_GRAPH,
                     0, 0, 0, 0, 0, 0);
  db_finalize(&q);
  style_footer();
}

/*
** WEBPAGE: tkthistory
** URL: /tkthistory?name=TICKETUUID
**







<
|
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<







921
922
923
924
925
926
927

928

























929
930
931
932
933
934
935
  canonical16(zGlobPattern, strlen(zGlobPattern));
  tagid = db_int(0, "SELECT tagid FROM tag WHERE tagname GLOB 'tkt-%q*'",zUuid);
  if( tagid==0 ){
    @ No such ticket: %h(zUuid)
    style_footer();
    return;
  }

  tkt_draw_timeline(tagid, zType);

























  style_footer();
}

/*
** WEBPAGE: tkthistory
** URL: /tkthistory?name=TICKETUUID
**