/* ** WEBPAGE: tktview ** URL: tktview?name=UUID ** ** View a ticket. */ void tktview_page(void){ const char *zScript; char *zFullName; const char *zUuid = PD("name",""); login_check_credentials(); if( !g.perm.RdTkt ){ login_needed(); return; } if( g.perm.WrTkt || g.perm.ApndTkt ){ style_submenu_element("Edit", "Edit The Ticket", "%s/tktedit?name=%T", g.zTop, PD("name","")); } if( g.perm.History ){ style_submenu_element("History", "History Of This Ticket", "%s/tkthistory/%T", g.zTop, zUuid); style_submenu_element("Timeline", "Timeline Of This Ticket", "%s/tkttimeline/%T", g.zTop, zUuid); style_submenu_element("Check-ins", "Check-ins Of This Ticket", "%s/tkttimeline/%T?y=ci", g.zTop, zUuid); } if( g.perm.NewTkt ){ style_submenu_element("New Ticket", "Create a new ticket", "%s/tktnew", g.zTop); } if( g.perm.ApndTkt && g.perm.Attach ){ style_submenu_element("Attach", "Add An Attachment", "%s/attachadd?tkt=%T&from=%s/tktview/%t", g.zTop, zUuid, g.zTop, zUuid); } style_header("View Ticket"); if( g.thTrace ) Th_Trace("BEGIN_TKTVIEW<br />\n", -1); ticket_init(); initializeVariablesFromDb(); zScript = ticket_viewpage_code(); if( g.thTrace ) Th_Trace("BEGIN_TKTVIEW_SCRIPT<br />\n", -1); Th_Render(zScript); if( g.thTrace ) Th_Trace("END_TKTVIEW<br />\n", -1); zFullName = db_text(0, "SELECT tkt_uuid FROM ticket" " WHERE tkt_uuid GLOB '%q*'", zUuid); if( zFullName ){ int cnt = 0; Stmt q; db_prepare(&q, "SELECT datetime(mtime,'localtime'), filename, user" " FROM attachment" " WHERE isLatest AND src!='' AND target=%Q" " ORDER BY mtime DESC", zFullName); while( db_step(&q)==SQLITE_ROW ){ const char *zDate = db_column_text(&q, 0); const char *zFile = db_column_text(&q, 1); const char *zUser = db_column_text(&q, 2); if( cnt==0 ){ @ <hr /><h2>Attachments:</h2> @ <ul> } cnt++; @ <li> if( g.perm.Read && g.perm.History ){ @ <a href="%s(g.zTop)/attachview?tkt=%s(zFullName)&file=%t(zFile)"> @ %h(zFile)</a> }else{ @ %h(zFile) } @ added by %h(zUser) on hyperlink_to_date(zDate, "."); if( g.perm.WrTkt && g.perm.Attach ){ @ [<a href="%s(g.zTop)/attachdelete?tkt=%s(zFullName)&file=%t(zFile)&from=%s(g.zTop)/tktview%%3fname=%s(zFullName)">delete</a>] }
/* ** WEBPAGE: tkthistory ** URL: /tkthistory?name=TICKETUUID ** ** Show the complete change history for a single ticket */ void tkthistory_page(void){ Stmt q; char *zTitle; const char *zUuid; int tagid; int nChng = 0; login_check_credentials(); if( !g.perm.Hyperlink || !g.perm.RdTkt ){ login_needed(); return; } zUuid = PD("name",""); zTitle = mprintf("History Of Ticket %h", zUuid); style_submenu_element("Status", "Status", "%s/info/%s", g.zTop, zUuid); style_submenu_element("Check-ins", "Check-ins", "%s/tkttimeline?name=%s&y=ci", g.zTop, zUuid); style_submenu_element("Timeline", "Timeline", "%s/tkttimeline?name=%s", g.zTop, zUuid); if( P("plaintext")!=0 ){ style_submenu_element("Formatted", "Formatted", "%R/tkthistory/%S", zUuid); }else{ style_submenu_element("Plaintext", "Plaintext", "%R/tkthistory/%S?plaintext", zUuid); } style_header(zTitle); free(zTitle); tagid = db_int(0, "SELECT tagid FROM tag WHERE tagname GLOB 'tkt-%q*'",zUuid); if( tagid==0 ){ cgi_printf("No such ticket: %h\n",(zUuid)); style_footer(); return; } db_prepare(&q, "SELECT datetime(mtime%s), objid, uuid, NULL, NULL, NULL" " FROM event, blob" " WHERE objid IN (SELECT rid FROM tagxref WHERE tagid=%d)" " AND blob.rid=event.objid" " UNION " "SELECT datetime(mtime%s), attachid, uuid, src, filename, user" " FROM attachment, blob" " WHERE target=(SELECT substr(tagname,5) FROM tag WHERE tagid=%d)" " AND blob.rid=attachid" " ORDER BY 1", timeline_utc(), tagid, timeline_utc(), tagid ); while( db_step(&q)==SQLITE_ROW ){ Manifest *pTicket; char zShort[12]; const char *zDate = db_column_text(&q, 0); int rid = db_column_int(&q, 1); const char *zChngUuid = db_column_text(&q, 2); const char *zFile = db_column_text(&q, 4); memcpy(zShort, zChngUuid, 10); zShort[10] = 0; if( nChng==0 ){ cgi_printf("<ol>\n"); } nChng++; if( zFile!=0 ){ const char *zSrc = db_column_text(&q, 3); const char *zUser = db_column_text(&q, 5); if( zSrc==0 || zSrc[0]==0 ){ cgi_printf("\n" "<li><p>Delete attachment \"%h\"\n",(zFile)); }else{ cgi_printf("\n" "<li><p>Add attachment\n" "\"%z%s</a>\"\n",(href("%R/artifact/%S",zSrc)),(zFile)); } cgi_printf("[%z%s</a>]\n" "(rid %d) by\n",(href("%R/artifact/%T",zChngUuid)),(zShort),(rid)); hyperlink_to_user(zUser,zDate," on"); hyperlink_to_date(zDate, ".</p>"); }else{ pTicket = manifest_get(rid, CFTYPE_TICKET, 0); if( pTicket ){ cgi_printf("\n" "<li><p>Ticket change\n" "[%z%s</a>]\n" "(rid %d) by\n",(href("%R/artifact/%T",zChngUuid)),(zShort),(rid)); hyperlink_to_user(pTicket->zUser,zDate," on"); hyperlink_to_date(zDate, ":"); cgi_printf("</p>\n"); ticket_output_change_artifact(pTicket, "a"); } manifest_destroy(pTicket); } } db_finalize(&q); if( nChng ){ cgi_printf("</ol>\n"); } style_footer(); }