| | @@ -29,15 +29,14 @@ |
| 29 | 29 | # define SQLITE_RECURSIVE 33 |
| 30 | 30 | #endif |
| 31 | 31 | |
| 32 | 32 | /* Settings that can be used to control ticket reports */ |
| 33 | 33 | /* |
| 34 | | -** SETTING: ticket-search-empty-report-number width=10 default=0 |
| 35 | | -** |
| 36 | | -** If this setting has an integer value of N, then when the ticket |
| 37 | | -** search page query is blank, the report with rn=N is shown. |
| 38 | | -** If N is zero, then no report is shown. |
| 34 | +** SETTING: ticket-default-report width=80 |
| 35 | +** If this setting has a string value, then when the ticket |
| 36 | +** search page query is blank, the report with this title is shown. |
| 37 | +** If the setting is blank (default), then no report is shown. |
| 39 | 38 | */ |
| 40 | 39 | |
| 41 | 40 | /* |
| 42 | 41 | ** WEBPAGE: reportlist |
| 43 | 42 | ** |
| | @@ -47,10 +46,11 @@ |
| 47 | 46 | const char *zScript; |
| 48 | 47 | Blob ril; /* Report Item List */ |
| 49 | 48 | Stmt q; |
| 50 | 49 | int rn = 0; |
| 51 | 50 | int cnt = 0; |
| 51 | + char *defaultReport = db_get("ticket-default-report", 0); |
| 52 | 52 | |
| 53 | 53 | login_check_credentials(); |
| 54 | 54 | if( !g.perm.RdTkt && !g.perm.NewTkt ){ |
| 55 | 55 | login_needed(g.anon.RdTkt || g.anon.NewTkt); |
| 56 | 56 | return; |
| | @@ -94,10 +94,13 @@ |
| 94 | 94 | href("%R/rptedit?rn=%d", rn)); |
| 95 | 95 | } |
| 96 | 96 | if( g.perm.TktFmt ){ |
| 97 | 97 | blob_appendf(&ril, "[%zsql</a>]", |
| 98 | 98 | href("%R/rptsql?rn=%d", rn)); |
| 99 | + } |
| 100 | + if( fossil_strcmp(zTitle, defaultReport)==0 ){ |
| 101 | + blob_appendf(&ril, " ← default"); |
| 99 | 102 | } |
| 100 | 103 | blob_appendf(&ril, "</li>\n"); |
| 101 | 104 | } |
| 102 | 105 | db_finalize(&q); |
| 103 | 106 | |
| | @@ -393,10 +396,11 @@ |
| 393 | 396 | const char *z; |
| 394 | 397 | const char *zOwner; |
| 395 | 398 | const char *zClrKey; |
| 396 | 399 | char *zSQL; |
| 397 | 400 | char *zErr = 0; |
| 401 | + int dflt = P("dflt") ? 1 : 0; |
| 398 | 402 | |
| 399 | 403 | login_check_credentials(); |
| 400 | 404 | if( !g.perm.TktFmt ){ |
| 401 | 405 | login_needed(g.anon.TktFmt); |
| 402 | 406 | return; |
| | @@ -461,10 +465,18 @@ |
| 461 | 465 | }else{ |
| 462 | 466 | db_multi_exec("INSERT INTO reportfmt(title,sqlcode,owner,cols,mtime) " |
| 463 | 467 | "VALUES(%Q,%Q,%Q,%Q,now())", |
| 464 | 468 | zTitle, zSQL, zOwner, zClrKey); |
| 465 | 469 | rn = db_last_insert_rowid(); |
| 470 | + } |
| 471 | + if( dflt ){ |
| 472 | + db_set("ticket-default-report", zTitle, 0); |
| 473 | + }else{ |
| 474 | + char *defaultReport = db_get("ticket-default-report", 0); |
| 475 | + if( fossil_strcmp(zTitle, defaultReport)==0 ){ |
| 476 | + db_set("ticket-default-report", "", 0); |
| 477 | + } |
| 466 | 478 | } |
| 467 | 479 | cgi_redirect(mprintf("rptview?rn=%d", rn)); |
| 468 | 480 | return; |
| 469 | 481 | } |
| 470 | 482 | }else if( rn==0 ){ |
| | @@ -474,14 +486,16 @@ |
| 474 | 486 | }else{ |
| 475 | 487 | Stmt q; |
| 476 | 488 | db_prepare(&q, "SELECT title, sqlcode, owner, cols " |
| 477 | 489 | "FROM reportfmt WHERE rn=%d",rn); |
| 478 | 490 | if( db_step(&q)==SQLITE_ROW ){ |
| 491 | + char *defaultReport = db_get("ticket-default-report", 0); |
| 479 | 492 | zTitle = db_column_malloc(&q, 0); |
| 480 | 493 | zSQL = db_column_malloc(&q, 1); |
| 481 | 494 | zOwner = db_column_malloc(&q, 2); |
| 482 | 495 | zClrKey = db_column_malloc(&q, 3); |
| 496 | + dflt = fossil_strcmp(zTitle, defaultReport)==0; |
| 483 | 497 | } |
| 484 | 498 | db_finalize(&q); |
| 485 | 499 | if( P("copy") ){ |
| 486 | 500 | rn = 0; |
| 487 | 501 | zTitle = mprintf("Copy Of %s", zTitle); |
| | @@ -516,10 +530,12 @@ |
| 516 | 530 | @ color key is displayed.) Each line contains the text for a single |
| 517 | 531 | @ entry in the key. The first token of each line is the background |
| 518 | 532 | @ color for that line.<br /> |
| 519 | 533 | @ <textarea name="k" rows="8" cols="50">%h(zClrKey)</textarea> |
| 520 | 534 | @ </p> |
| 535 | + @ <p><label><input type="checkbox" name="dflt" %s(dflt?"checked":"")> \ |
| 536 | + @ Make this the default report</label></p> |
| 521 | 537 | if( !g.perm.Admin && fossil_strcmp(zOwner,g.zLogin)!=0 ){ |
| 522 | 538 | @ <p>This report format is owned by %h(zOwner). You are not allowed |
| 523 | 539 | @ to change it.</p> |
| 524 | 540 | @ </form> |
| 525 | 541 | report_format_hints(); |
| | @@ -998,16 +1014,17 @@ |
| 998 | 1014 | |
| 999 | 1015 | /* |
| 1000 | 1016 | ** Render a report. |
| 1001 | 1017 | */ |
| 1002 | 1018 | void rptview_page_content( |
| 1003 | | - int rn, /* Report number. If 0, retrieve from rn query parameter. */ |
| 1019 | + const char *defaultTitleSearch, /* If rn and title query parameters are |
| 1020 | + blank, search reports by this title. */ |
| 1004 | 1021 | int pageWrap, /* If true, render full page; otherwise, just the report */ |
| 1005 | 1022 | int redirectMissing /* If true and report not found, go to reportlist */ |
| 1006 | 1023 | ){ |
| 1007 | 1024 | int count = 0; |
| 1008 | | - int rc; |
| 1025 | + int rn, rc; |
| 1009 | 1026 | char *zSql; |
| 1010 | 1027 | char *zTitle; |
| 1011 | 1028 | char *zOwner; |
| 1012 | 1029 | char *zClrKey; |
| 1013 | 1030 | int tabs; |
| | @@ -1016,27 +1033,27 @@ |
| 1016 | 1033 | char *zErr2 = 0; |
| 1017 | 1034 | |
| 1018 | 1035 | login_check_credentials(); |
| 1019 | 1036 | if( !g.perm.RdTkt ){ login_needed(g.anon.RdTkt); return; } |
| 1020 | 1037 | tabs = P("tablist")!=0; |
| 1021 | | - if ( rn==0 ) { |
| 1022 | | - rn = atoi(PD("rn","0")); |
| 1023 | | - } |
| 1024 | 1038 | db_prepare(&q, |
| 1025 | 1039 | "SELECT title, sqlcode, owner, cols, rn FROM reportfmt WHERE rn=%d", |
| 1026 | | - rn); |
| 1040 | + atoi(PD("rn","0"))); |
| 1027 | 1041 | rc = db_step(&q); |
| 1028 | 1042 | if( rc!=SQLITE_ROW ){ |
| 1043 | + const char *titleSearch = |
| 1044 | + defaultTitleSearch==0 || trim_string(defaultTitleSearch)[0]==0 ? |
| 1045 | + P("title") : defaultTitleSearch; |
| 1029 | 1046 | db_finalize(&q); |
| 1030 | 1047 | db_prepare(&q, |
| 1031 | 1048 | "SELECT title, sqlcode, owner, cols, rn FROM reportfmt WHERE title GLOB %Q", |
| 1032 | | - P("title")); |
| 1049 | + titleSearch); |
| 1033 | 1050 | rc = db_step(&q); |
| 1034 | 1051 | } |
| 1035 | 1052 | if( rc!=SQLITE_ROW ){ |
| 1036 | 1053 | db_finalize(&q); |
| 1037 | | - if (redirectMissing) { |
| 1054 | + if( redirectMissing ) { |
| 1038 | 1055 | cgi_redirect("reportlist"); |
| 1039 | 1056 | } |
| 1040 | 1057 | return; |
| 1041 | 1058 | } |
| 1042 | 1059 | zTitle = db_column_malloc(&q, 0); |
| | @@ -1066,11 +1083,11 @@ |
| 1066 | 1083 | struct GenerateHTML sState = { 0, 0, 0, 0, 0, 0, 0, 0, 0 }; |
| 1067 | 1084 | const char *zQS = PD("QUERY_STRING",""); |
| 1068 | 1085 | |
| 1069 | 1086 | db_multi_exec("PRAGMA empty_result_callbacks=ON"); |
| 1070 | 1087 | style_set_current_feature("report"); |
| 1071 | | - if ( pageWrap ) { |
| 1088 | + if( pageWrap ) { |
| 1072 | 1089 | /* style_finish_page() should provide escaping via %h formatting */ |
| 1073 | 1090 | if( zQS[0] ){ |
| 1074 | 1091 | style_submenu_element("Raw","%R/%s?tablist=1&%s",g.zPath,zQS); |
| 1075 | 1092 | style_submenu_element("Reports","%R/reportlist?%s",zQS); |
| 1076 | 1093 | } else { |
| | @@ -1103,11 +1120,11 @@ |
| 1103 | 1120 | @ <p class="reportError">Error: %h(zErr1)</p> |
| 1104 | 1121 | }else if( zErr2 ){ |
| 1105 | 1122 | @ <p class="reportError">Error: %h(zErr2)</p> |
| 1106 | 1123 | } |
| 1107 | 1124 | style_table_sorter(); |
| 1108 | | - if ( pageWrap ) { |
| 1125 | + if( pageWrap ) { |
| 1109 | 1126 | style_finish_page(); |
| 1110 | 1127 | } |
| 1111 | 1128 | }else{ |
| 1112 | 1129 | report_restrict_sql(&zErr1); |
| 1113 | 1130 | db_exec_readonly(g.db, zSql, output_tab_separated, &count, &zErr2); |
| 1114 | 1131 | |