02d1ed6ad2 2008-02-02 stephan: /* 02d1ed6ad2 2008-02-02 stephan: ** Copyright (c) 2007 D. Richard Hipp 2ab3a2f603 2008-02-03 stephan: ** Copyright (c) 2008 Stephan Beal 02d1ed6ad2 2008-02-02 stephan: ** 02d1ed6ad2 2008-02-02 stephan: ** This program is free software; you can redistribute it and/or 02d1ed6ad2 2008-02-02 stephan: ** modify it under the terms of the GNU General Public 02d1ed6ad2 2008-02-02 stephan: ** License as published by the Free Software Foundation; either 02d1ed6ad2 2008-02-02 stephan: ** version 2 of the License, or (at your option) any later version. 02d1ed6ad2 2008-02-02 stephan: ** 02d1ed6ad2 2008-02-02 stephan: ** This program is distributed in the hope that it will be useful, 02d1ed6ad2 2008-02-02 stephan: ** but WITHOUT ANY WARRANTY; without even the implied warranty of 02d1ed6ad2 2008-02-02 stephan: ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 02d1ed6ad2 2008-02-02 stephan: ** General Public License for more details. 02d1ed6ad2 2008-02-02 stephan: ** 02d1ed6ad2 2008-02-02 stephan: ** You should have received a copy of the GNU General Public 02d1ed6ad2 2008-02-02 stephan: ** License along with this library; if not, write to the 02d1ed6ad2 2008-02-02 stephan: ** Free Software Foundation, Inc., 59 Temple Place - Suite 330, 02d1ed6ad2 2008-02-02 stephan: ** Boston, MA 02111-1307, USA. 02d1ed6ad2 2008-02-02 stephan: ** 02d1ed6ad2 2008-02-02 stephan: ** Author contact information: 02d1ed6ad2 2008-02-02 stephan: ** drh@hwaci.com 02d1ed6ad2 2008-02-02 stephan: ** http://www.hwaci.com/drh/ 02d1ed6ad2 2008-02-02 stephan: ** 02d1ed6ad2 2008-02-02 stephan: ******************************************************************************* 02d1ed6ad2 2008-02-02 stephan: ** 02d1ed6ad2 2008-02-02 stephan: ** Implementation of the Tag View page 02d1ed6ad2 2008-02-02 stephan: */ 02d1ed6ad2 2008-02-02 stephan: #include <assert.h> 02d1ed6ad2 2008-02-02 stephan: #include "config.h" 02d1ed6ad2 2008-02-02 stephan: #include "tagview.h" 02d1ed6ad2 2008-02-02 stephan: a12cb216b7 2009-01-22 drh: #if 0 /* DISABLED */ 02a7c850b4 2008-02-03 stephan: 02a7c850b4 2008-02-03 stephan: #if 0 2cb3290e67 2008-02-03 stephan: # define TAGVIEW_DEFAULT_FILTER "AND t.tagname NOT GLOB 'wiki-*' " 2cb3290e67 2008-02-03 stephan: #else 2cb3290e67 2008-02-03 stephan: # define TAGVIEW_DEFAULT_FILTER 02a7c850b4 2008-02-03 stephan: #endif 2ab3a2f603 2008-02-03 stephan: 2ab3a2f603 2008-02-03 stephan: /* 007d1ce44f 2008-02-07 drh: ** Lists all tags matching the given LIKE clause (which 007d1ce44f 2008-02-07 drh: ** may be 0). 2ab3a2f603 2008-02-03 stephan: */ 007d1ce44f 2008-02-07 drh: static void tagview_page_list_tags(const char *zLike){ 007d1ce44f 2008-02-07 drh: char *zLikeClause = 0; 9c01af2d22 2008-02-03 stephan: const int limit = 10; 007d1ce44f 2008-02-07 drh: char *zLimit = 0; 007d1ce44f 2008-02-07 drh: char *zSql; 2cb3290e67 2008-02-03 stephan: 007d1ce44f 2008-02-07 drh: if( zLike && zLike[0] ){ 007d1ce44f 2008-02-07 drh: zLikeClause = mprintf( "AND t.tagname LIKE '%%%q%%'", zLike ); 007d1ce44f 2008-02-07 drh: zLimit = ""; 007d1ce44f 2008-02-07 drh: @ <h2>Tags matching [%h(zLikeClause)]:</h2> 2ab3a2f603 2008-02-03 stephan: }else{ 007d1ce44f 2008-02-07 drh: zLimit = mprintf( "LIMIT %d", limit ); 007d1ce44f 2008-02-07 drh: zLikeClause = ""; 2ab3a2f603 2008-02-03 stephan: @ <h2>%d(limit) most recent tags:</h2> 2ab3a2f603 2008-02-03 stephan: } 007d1ce44f 2008-02-07 drh: zSql = mprintf( 007d1ce44f 2008-02-07 drh: "SELECT " 007d1ce44f 2008-02-07 drh: " linktagid(t.tagid) AS 'Tag ID'," 007d1ce44f 2008-02-07 drh: " linktagname(t.tagname) AS 'Name'," 007d1ce44f 2008-02-07 drh: " DATETIME(tx.mtime) AS 'Timestamp'," 007d1ce44f 2008-02-07 drh: " linkuuid(b.uuid) AS 'Version'" 007d1ce44f 2008-02-07 drh: " FROM tag t, tagxref tx, blob b " 0ff4e918f4 2008-02-13 stephan: " WHERE t.tagid=tx.tagid AND tx.rid=b.rid" 7c281b629a 2008-12-20 eric: " %s " 9c01af2d22 2008-02-03 stephan: TAGVIEW_DEFAULT_FILTER 007d1ce44f 2008-02-07 drh: " ORDER BY tx.mtime DESC %s", 007d1ce44f 2008-02-07 drh: zLikeClause, zLimit 007d1ce44f 2008-02-07 drh: ); 007d1ce44f 2008-02-07 drh: db_generic_query_view(zSql, 1); 007d1ce44f 2008-02-07 drh: free(zSql); 6d67f3c7c7 2008-02-08 stephan: if( zLikeClause[0] ) free(zLikeClause); 6d67f3c7c7 2008-02-08 stephan: if( zLimit[0] ) free(zLimit); 2ab3a2f603 2008-02-03 stephan: } 2ab3a2f603 2008-02-03 stephan: 007d1ce44f 2008-02-07 drh: /* 007d1ce44f 2008-02-07 drh: ** A small search form which forwards to ?like=SEARCH_STRING 9c01af2d22 2008-02-03 stephan: */ 2ab3a2f603 2008-02-03 stephan: static void tagview_page_search_miniform(void){ 2ab3a2f603 2008-02-03 stephan: char const * like = P("like"); 8d529a7ae9 2008-11-26 eric: @ <div class='miniform'> 3984b1b2c1 2008-08-04 eric: @ <form action='tagview' method='post'> 2ab3a2f603 2008-02-03 stephan: @ Search for tags: 007d1ce44f 2008-02-07 drh: @ <input type='text' name='like' value='%h((like?like:""))' size='10'/> 2ab3a2f603 2008-02-03 stephan: @ <input type='submit'/> 10df4ff603 2008-11-25 eric: @ <input type='hidden' name='raw' value='y'/> 2ab3a2f603 2008-02-03 stephan: @ </form> 2ab3a2f603 2008-02-03 stephan: @ </div> 2ab3a2f603 2008-02-03 stephan: } 2ab3a2f603 2008-02-03 stephan: 007d1ce44f 2008-02-07 drh: /* 007d1ce44f 2008-02-07 drh: ** tagview_page_default() renders the default page for tagview_page(). 9c01af2d22 2008-02-03 stephan: */ 2ab3a2f603 2008-02-03 stephan: static void tagview_page_default(void){ 2ab3a2f603 2008-02-03 stephan: tagview_page_list_tags( 0 ); 2ab3a2f603 2008-02-03 stephan: } 2ab3a2f603 2008-02-03 stephan: 007d1ce44f 2008-02-07 drh: /* 007d1ce44f 2008-02-07 drh: ** Lists all tags matching the given tagid. 9c01af2d22 2008-02-03 stephan: */ 007d1ce44f 2008-02-07 drh: static void tagview_page_tag_by_id( int tagid ){ 007d1ce44f 2008-02-07 drh: char *zSql; 9c01af2d22 2008-02-03 stephan: @ <h2>Tag #%d(tagid):</h2> 007d1ce44f 2008-02-07 drh: zSql = mprintf( 007d1ce44f 2008-02-07 drh: "SELECT DISTINCT" 007d1ce44f 2008-02-07 drh: " linktagname(t.tagname) AS 'Tag Name'," 007d1ce44f 2008-02-07 drh: " DATETIME(tx.mtime) AS 'Timestamp'," 007d1ce44f 2008-02-07 drh: " linkuuid(b.uuid) AS 'Version'" 007d1ce44f 2008-02-07 drh: " FROM tag t, tagxref tx, blob b" 0ff4e918f4 2008-02-13 stephan: " WHERE t.tagid=%d AND t.tagid=tx.tagid AND tx.rid=b.rid " 9c01af2d22 2008-02-03 stephan: TAGVIEW_DEFAULT_FILTER 007d1ce44f 2008-02-07 drh: " ORDER BY tx.mtime DESC", 007d1ce44f 2008-02-07 drh: tagid 007d1ce44f 2008-02-07 drh: ); 007d1ce44f 2008-02-07 drh: db_generic_query_view(zSql, 1); 007d1ce44f 2008-02-07 drh: free(zSql); 02a7c850b4 2008-02-03 stephan: } 02a7c850b4 2008-02-03 stephan: 007d1ce44f 2008-02-07 drh: /* 007d1ce44f 2008-02-07 drh: ** Lists all tags matching the given tag name. 02a7c850b4 2008-02-03 stephan: */ 007d1ce44f 2008-02-07 drh: static void tagview_page_tag_by_name( char const * tagname ){ 007d1ce44f 2008-02-07 drh: char *zSql; 9c01af2d22 2008-02-03 stephan: @ <h2>Tag '%s(tagname)':</h2> 007d1ce44f 2008-02-07 drh: zSql = mprintf( 007d1ce44f 2008-02-07 drh: "SELECT DISTINCT" 007d1ce44f 2008-02-07 drh: " linktagid(t.tagid) AS 'Tag ID'," 8d529a7ae9 2008-11-26 eric: " linktagname(t.tagname) AS 'Name'," 007d1ce44f 2008-02-07 drh: " DATETIME(tx.mtime) AS 'Timestamp'," 007d1ce44f 2008-02-07 drh: " linkuuid(b.uuid) AS 'Version'" 007d1ce44f 2008-02-07 drh: " FROM tag t, tagxref tx, blob b " 8d529a7ae9 2008-11-26 eric: " WHERE ( t.tagname='%q' OR t.tagname='sym-%q') " 8d529a7ae9 2008-11-26 eric: " AND t.tagid=tx.tagid AND tx.rid=b.rid " 9c01af2d22 2008-02-03 stephan: TAGVIEW_DEFAULT_FILTER 007d1ce44f 2008-02-07 drh: " ORDER BY tx.mtime DESC", 8d529a7ae9 2008-11-26 eric: tagname,tagname); 007d1ce44f 2008-02-07 drh: db_generic_query_view(zSql, 1); 007d1ce44f 2008-02-07 drh: free(zSql); 2ab3a2f603 2008-02-03 stephan: } 02d1ed6ad2 2008-02-02 stephan: 02d1ed6ad2 2008-02-02 stephan: /* 10df4ff603 2008-11-25 eric: ** Internal view of tags 02d1ed6ad2 2008-02-02 stephan: */ 10df4ff603 2008-11-25 eric: void raw_tagview_page(void){ 908009fdc4 2008-05-07 drh: char const * check = 0; 9c01af2d22 2008-02-03 stephan: login_check_credentials(); 10df4ff603 2008-11-25 eric: /* if( !g.okRdWiki ){ */ 10df4ff603 2008-11-25 eric: if( !g.okAdmin ){ 9c01af2d22 2008-02-03 stephan: login_needed(); 2ab3a2f603 2008-02-03 stephan: } 8d529a7ae9 2008-11-26 eric: style_header("Raw Tags"); d57de28756 2008-05-05 drh: login_anonymous_available(); 2ab3a2f603 2008-02-03 stephan: tagview_page_search_miniform(); 2ab3a2f603 2008-02-03 stephan: @ <hr/> 007d1ce44f 2008-02-07 drh: if( 0 != (check = P("tagid")) ){ 2ab3a2f603 2008-02-03 stephan: tagview_page_tag_by_id( atoi(check) ); 007d1ce44f 2008-02-07 drh: }else if( 0 != (check = P("like")) ){ 2ab3a2f603 2008-02-03 stephan: tagview_page_list_tags( check ); 007d1ce44f 2008-02-07 drh: }else if( 0 != (check = P("name")) ){ 2ab3a2f603 2008-02-03 stephan: tagview_page_tag_by_name( check ); 02d1ed6ad2 2008-02-02 stephan: }else{ 2ab3a2f603 2008-02-03 stephan: tagview_page_default(); 02d1ed6ad2 2008-02-02 stephan: } 2ab3a2f603 2008-02-03 stephan: style_footer(); 2ab3a2f603 2008-02-03 stephan: } 9c01af2d22 2008-02-03 stephan: 9c01af2d22 2008-02-03 stephan: #undef TAGVIEW_DEFAULT_FILTER 02a7c850b4 2008-02-03 stephan: 0e924820bf 2008-08-24 eric: /* 0e924820bf 2008-08-24 eric: ** Generate a timeline for the chosen tag 0e924820bf 2008-08-24 eric: */ b7f32a71ab 2009-01-20 drh: void tagview_print_timeline(char const *zName, char const *zPrefix){ 0e924820bf 2008-08-24 eric: char *zSql; 0e924820bf 2008-08-24 eric: Stmt q; b7f32a71ab 2009-01-20 drh: int tagid = db_int(0, "SELECT tagid FROM tag WHERE tagname='%q%q'", b7f32a71ab 2009-01-20 drh: zPrefix, zName); 0e924820bf 2008-08-24 eric: zSql = mprintf("%s AND EXISTS (SELECT 1" 0e924820bf 2008-08-24 eric: " FROM tagxref" 0e924820bf 2008-08-24 eric: " WHERE tagxref.rid = event.objid" 7c281b629a 2008-12-20 eric: " AND tagxref.tagtype > 0" bf7ca1a4d8 2009-01-20 drh: " AND tagxref.tagid = %d)" 0e924820bf 2008-08-24 eric: " ORDER BY 3 desc", b7f32a71ab 2009-01-20 drh: timeline_query_for_www(), tagid b7f32a71ab 2009-01-20 drh: ); 0e924820bf 2008-08-24 eric: db_prepare(&q, zSql); 0e924820bf 2008-08-24 eric: free(zSql); 580d6ad8c7 2009-01-21 drh: www_print_timeline(&q, 0, 0); 0e924820bf 2008-08-24 eric: db_finalize(&q); 02d1ed6ad2 2008-02-02 stephan: } 02d1ed6ad2 2008-02-02 stephan: 02d1ed6ad2 2008-02-02 stephan: /* a12cb216b7 2009-01-22 drh: ** WEB PAGE: /tagview 02d1ed6ad2 2008-02-02 stephan: */ 02d1ed6ad2 2008-02-02 stephan: void tagview_page(void){ 3984b1b2c1 2008-08-04 eric: char const *zName = 0; 8d529a7ae9 2008-11-26 eric: char const *zTitle = 0; 3d62a9fb39 2008-10-06 drh: int nTag = 0; 02d1ed6ad2 2008-02-02 stephan: login_check_credentials(); 3984b1b2c1 2008-08-04 eric: if( !g.okRead ){ 02d1ed6ad2 2008-02-02 stephan: login_needed(); 02d1ed6ad2 2008-02-02 stephan: } 10df4ff603 2008-11-25 eric: if ( P("tagid") || P("like") || P("raw") ) { 10df4ff603 2008-11-25 eric: raw_tagview_page(); 10df4ff603 2008-11-25 eric: return; 02a7c850b4 2008-02-03 stephan: } 3984b1b2c1 2008-08-04 eric: login_anonymous_available(); 3984b1b2c1 2008-08-04 eric: if( 0 != (zName = P("name")) ){ 3984b1b2c1 2008-08-04 eric: Blob uuid; 8d529a7ae9 2008-11-26 eric: if( g.okAdmin ){ 8d529a7ae9 2008-11-26 eric: style_submenu_element("RawTags", "Internal Ticket View", 8d529a7ae9 2008-11-26 eric: "%s/tagview?name=%s&raw=y", g.zTop, zName); 8d529a7ae9 2008-11-26 eric: } 8d529a7ae9 2008-11-26 eric: zTitle = "Tagged Artifacts"; 0e924820bf 2008-08-24 eric: @ <h2>%s(zName):</h2> 3984b1b2c1 2008-08-04 eric: if( sym_tag_to_uuid(zName, &uuid) > 0){ 0e924820bf 2008-08-24 eric: tagview_print_timeline(zName, "sym-"); 5fb14b9a0f 2008-08-21 eric: }else if( tag_to_uuid(zName, &uuid, "") > 0){ 0e924820bf 2008-08-24 eric: tagview_print_timeline(zName, ""); 0e924820bf 2008-08-24 eric: }else{ 3984b1b2c1 2008-08-04 eric: @ There is no artifact with this tag. 3984b1b2c1 2008-08-04 eric: } 3984b1b2c1 2008-08-04 eric: }else{ 3984b1b2c1 2008-08-04 eric: Stmt q; 3984b1b2c1 2008-08-04 eric: const char *prefix = "sym-"; 3984b1b2c1 2008-08-04 eric: int preflen = strlen(prefix); 8d529a7ae9 2008-11-26 eric: if( g.okAdmin ){ 8d529a7ae9 2008-11-26 eric: style_submenu_element("RawTags", "Internal Ticket View", 8d529a7ae9 2008-11-26 eric: "%s/tagview?raw=y", g.zTop); 8d529a7ae9 2008-11-26 eric: } 8d529a7ae9 2008-11-26 eric: zTitle = "Tags"; 3984b1b2c1 2008-08-04 eric: db_prepare(&q, 3984b1b2c1 2008-08-04 eric: "SELECT tagname" 3984b1b2c1 2008-08-04 eric: " FROM tag" 3984b1b2c1 2008-08-04 eric: " WHERE EXISTS(SELECT 1 FROM tagxref" 3984b1b2c1 2008-08-04 eric: " WHERE tagid=tag.tagid" 3984b1b2c1 2008-08-04 eric: " AND tagtype>0)" 5fb14b9a0f 2008-08-21 eric: " AND tagid > %d" 5fb14b9a0f 2008-08-21 eric: " AND tagname NOT GLOB 'wiki-*'" 5fb14b9a0f 2008-08-21 eric: " AND tagname NOT GLOB 'tkt-*'" 5fb14b9a0f 2008-08-21 eric: " ORDER BY tagname", 5fb14b9a0f 2008-08-21 eric: MAX_INT_TAG 02a7c850b4 2008-02-03 stephan: ); 3984b1b2c1 2008-08-04 eric: @ <ul> 3984b1b2c1 2008-08-04 eric: while( db_step(&q)==SQLITE_ROW ){ 3984b1b2c1 2008-08-04 eric: const char *name = db_column_text(&q, 0); 3d62a9fb39 2008-10-06 drh: nTag++; 5b87749575 2008-09-06 eric: if( g.okHistory ){ 5b87749575 2008-09-06 eric: if( strncmp(name, prefix, preflen)==0 ){ 5b87749575 2008-09-06 eric: @ <li><a href=%s(g.zBaseURL)/tagview?name=%s(name+preflen)> 5b87749575 2008-09-06 eric: @ %s(name+preflen)</a> 5b87749575 2008-09-06 eric: }else{ 5b87749575 2008-09-06 eric: @ <li><a href=%s(g.zBaseURL)/tagview?name=%s(name)> 5b87749575 2008-09-06 eric: @ %s(name)</a> 5b87749575 2008-09-06 eric: } 5fb14b9a0f 2008-08-21 eric: }else{ 5b87749575 2008-09-06 eric: if( strncmp(name, prefix, preflen)==0 ){ 5b87749575 2008-09-06 eric: @ <li><strong>%s(name+preflen)</strong> 5b87749575 2008-09-06 eric: }else{ 5b87749575 2008-09-06 eric: @ <li><strong>%s(name)</strong> 5b87749575 2008-09-06 eric: } 5b87749575 2008-09-06 eric: } 3984b1b2c1 2008-08-04 eric: if( strncmp(name, prefix, preflen)==0 ){ 5b87749575 2008-09-06 eric: @ (symbolic label) 3984b1b2c1 2008-08-04 eric: } 5b87749575 2008-09-06 eric: @ </li> 3984b1b2c1 2008-08-04 eric: } 3984b1b2c1 2008-08-04 eric: @ </ul> 3d62a9fb39 2008-10-06 drh: if( nTag == 0) { 5b87749575 2008-09-06 eric: @ There are no relevant tags. 5b87749575 2008-09-06 eric: } 3984b1b2c1 2008-08-04 eric: db_finalize(&q); 02d1ed6ad2 2008-02-02 stephan: } 8d529a7ae9 2008-11-26 eric: style_header(zTitle); 5b87749575 2008-09-06 eric: /* 5b87749575 2008-09-06 eric: * Put in dummy functions since www_print_timeline has generated calls to 5b87749575 2008-09-06 eric: * them. Some browsers don't seem to care, but better to be safe. 5b87749575 2008-09-06 eric: * Actually, it would be nice to use the functions on this page, but at 5b87749575 2008-09-06 eric: * the moment it looks to be too difficult. 5b87749575 2008-09-06 eric: */ 5b87749575 2008-09-06 eric: @ <script> 5b87749575 2008-09-06 eric: @ function xin(id){ 5b87749575 2008-09-06 eric: @ } 5b87749575 2008-09-06 eric: @ function xout(id){ 5b87749575 2008-09-06 eric: @ } 5b87749575 2008-09-06 eric: @ </script> 02a7c850b4 2008-02-03 stephan: 02d1ed6ad2 2008-02-02 stephan: style_footer(); 02d1ed6ad2 2008-02-02 stephan: } 02d1ed6ad2 2008-02-02 stephan: a12cb216b7 2009-01-22 drh: #endif /* DISABLED */