Fossil

Check-in [05105248]
Login

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

Overview
Comment:Add the /forum page with search and a list of recent threads.
Downloads: Tarball | ZIP archive | SQL archive
Timelines: family | ancestors | descendants | both | forum-v2
Files: files | file ages | folders
SHA3-256:05105248a1568220b61c85cbb271f9b08af570fa3f1f7e8b1a473b4bab92fa04
User & Date: drh 2018-07-31 04:08:22
Context
2018-07-31
04:18
Add the email alerts configuration summary to the security audit page. check-in: a9e67fe6 user: drh tags: forum-v2
04:08
Add the /forum page with search and a list of recent threads. check-in: 05105248 user: drh tags: forum-v2
03:14
Enable search over the forum. check-in: b3c1ba37 user: drh tags: forum-v2
Changes
Hide Diffs Unified Diffs Ignore Whitespace Patch

Changes to src/forum.c.

881
882
883
884
885
886
887



















































    @ <br><label><input type="checkbox" name="showqp" %s(PCK("showqp"))> \
    @ Show query parameters</label>
    @ </div>
  }
  @ </form>
  style_footer();
}


























































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
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
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
    @ <br><label><input type="checkbox" name="showqp" %s(PCK("showqp"))> \
    @ Show query parameters</label>
    @ </div>
  }
  @ </form>
  style_footer();
}

/*
** WEBPAGE: forum
**
** The main page for the forum feature.  Show a list of recent forum
** threads.  Also show a search box at the top if search is enabled,
** and a button for creating a new thread, if enabled.
*/
void forum_main_page(void){
  Stmt q;
  int iLimit, iOfst;
  login_check_credentials();
  sqlite3_int64 iNow = time(NULL);
  if( !g.perm.RdForum ){
    login_needed(g.anon.RdForum);
    return;
  }
  style_header("Forum");
  if( g.perm.WrForum ){
    style_submenu_element("New Message","%R/forumnew");
  }
  if( search_screen(SRCH_FORUM, 0) ){
    style_submenu_element("Recent Threads","%R/forum");
    style_footer();
    return;
  }
  iLimit = 50;
  iOfst = 0;
  @ <h1>Recent Threads</h1>
  @ <div class='fileage'><table width="100%%">
  db_prepare(&q,
     "SELECT julianday('now') - max(fmtime),"
     "       (SELECT uuid FROM blob WHERE rid=fpid),"
     "       (SELECT substr(comment,instr(comment,':')+2)"
     "          FROM event WHERE objid=fpid)"
     "  FROM forumpost"
     " GROUP BY froot ORDER BY 1 LIMIT %d OFFSET %d",
     iLimit, iOfst
  );
  while( db_step(&q)==SQLITE_ROW ){
    char *zAge = human_readable_age(db_column_double(&q,0));
    const char *zUuid = db_column_text(&q, 1);
    const char *zTitle = db_column_text(&q, 2);
    @ <tr><td>%h(zAge) ago</td>
    @ <td>%z(href("%R/forumpost/%S",zUuid))%h(zTitle)</a>
    @ </tr>
    fossil_free(zAge);
  }
  @ </table></div>
  style_footer();
}

Changes to src/search.c.

1064
1065
1066
1067
1068
1069
1070
1071
1072






1073
1074
1075
1076
1077
1078
1079
1080

1081
1082
1083
1084
1085
1086
1087
1088
1089
1090

1091
1092
1093
1094
1095
1096
1097
....
1099
1100
1101
1102
1103
1104
1105
1106
1107
1108
1109
1110
1111
1112
1113
....
1144
1145
1146
1147
1148
1149
1150

1151

1152
1153
1154
1155
1156
1157
1158
** categories.  Any srchFlags with two or more bits set
** is treated like SRCH_ALL for display purposes.
**
** This routine automatically restricts srchFlag according to user
** permissions and the server configuration.  The entry box is shown
** disabled if srchFlags is 0 after these restrictions are applied.
**
** If useYparam is true, then this routine also looks at the y= query
** parameter for further search restrictions.






*/
void search_screen(unsigned srchFlags, int useYparam){
  const char *zType = 0;
  const char *zClass = 0;
  const char *zDisable1;
  const char *zDisable2;
  const char *zPattern;
  int fDebug = PB("debug");

  srchFlags = search_restrict(srchFlags);
  switch( srchFlags ){
    case SRCH_CKIN:     zType = " Check-ins";  zClass = "Ckin"; break;
    case SRCH_DOC:      zType = " Docs";       zClass = "Doc";  break;
    case SRCH_TKT:      zType = " Tickets";    zClass = "Tkt";  break;
    case SRCH_WIKI:     zType = " Wiki";       zClass = "Wiki"; break;
    case SRCH_TECHNOTE: zType = " Tech Notes"; zClass = "Note"; break;
    case SRCH_FORUM:    zType = " Forum";      zClass = "Frm";  break;
  }
  if( srchFlags==0 ){

    zDisable1 = " disabled";
    zDisable2 = " disabled";
    zPattern = "";
  }else{
    zDisable1 = ""; /* Was: " autofocus" */
    zDisable2 = "";
    zPattern = PD("s","");
................................................................................
  @ <form method='GET' action='%R/%T(g.zPath)'>
  if( zClass ){
    @ <div class='searchForm searchForm%s(zClass)'>
  }else{
    @ <div class='searchForm'>
  }
  @ <input type="text" name="s" size="40" value="%h(zPattern)"%s(zDisable1)>
  if( useYparam && (srchFlags & (srchFlags-1))!=0 && useYparam ){
    static const struct { char *z; char *zNm; unsigned m; } aY[] = {
       { "all",  "All",        SRCH_ALL      },
       { "c",    "Check-ins",  SRCH_CKIN     },
       { "d",    "Docs",       SRCH_DOC      },
       { "t",    "Tickets",    SRCH_TKT      },
       { "w",    "Wiki",       SRCH_WIKI     },
       { "e",    "Tech Notes", SRCH_TECHNOTE },
................................................................................
    }else{
      @ <div class='searchResult'>
    }
    if( search_run_and_output(zPattern, srchFlags, fDebug)==0 ){
      @ <p class='searchEmpty'>No matches for: <span>%h(zPattern)</span></p>
    }
    @ </div>

  }

}

/*
** WEBPAGE: search
**
** Search for check-in comments, documents, tickets, or wiki that
** match a user-supplied pattern.







|
|
>
>
>
>
>
>

|






>










>







 







|







 







>

>







1064
1065
1066
1067
1068
1069
1070
1071
1072
1073
1074
1075
1076
1077
1078
1079
1080
1081
1082
1083
1084
1085
1086
1087
1088
1089
1090
1091
1092
1093
1094
1095
1096
1097
1098
1099
1100
1101
1102
1103
1104
1105
....
1107
1108
1109
1110
1111
1112
1113
1114
1115
1116
1117
1118
1119
1120
1121
....
1152
1153
1154
1155
1156
1157
1158
1159
1160
1161
1162
1163
1164
1165
1166
1167
1168
** categories.  Any srchFlags with two or more bits set
** is treated like SRCH_ALL for display purposes.
**
** This routine automatically restricts srchFlag according to user
** permissions and the server configuration.  The entry box is shown
** disabled if srchFlags is 0 after these restrictions are applied.
**
** The mFlags value controls options:
**
**     0x01    If the y= query parameter is present, use it as an addition
**             restriction what to search.
**
**     0x02    Show nothing if search is disabled.
**
** Return true if there are search results.
*/
int search_screen(unsigned srchFlags, int mFlags){
  const char *zType = 0;
  const char *zClass = 0;
  const char *zDisable1;
  const char *zDisable2;
  const char *zPattern;
  int fDebug = PB("debug");
  int haveResult = 0;
  srchFlags = search_restrict(srchFlags);
  switch( srchFlags ){
    case SRCH_CKIN:     zType = " Check-ins";  zClass = "Ckin"; break;
    case SRCH_DOC:      zType = " Docs";       zClass = "Doc";  break;
    case SRCH_TKT:      zType = " Tickets";    zClass = "Tkt";  break;
    case SRCH_WIKI:     zType = " Wiki";       zClass = "Wiki"; break;
    case SRCH_TECHNOTE: zType = " Tech Notes"; zClass = "Note"; break;
    case SRCH_FORUM:    zType = " Forum";      zClass = "Frm";  break;
  }
  if( srchFlags==0 ){
    if( mFlags & 0x02 ) return 0;
    zDisable1 = " disabled";
    zDisable2 = " disabled";
    zPattern = "";
  }else{
    zDisable1 = ""; /* Was: " autofocus" */
    zDisable2 = "";
    zPattern = PD("s","");
................................................................................
  @ <form method='GET' action='%R/%T(g.zPath)'>
  if( zClass ){
    @ <div class='searchForm searchForm%s(zClass)'>
  }else{
    @ <div class='searchForm'>
  }
  @ <input type="text" name="s" size="40" value="%h(zPattern)"%s(zDisable1)>
  if( (mFlags & 0x01)!=0 && (srchFlags & (srchFlags-1))!=0 ){
    static const struct { char *z; char *zNm; unsigned m; } aY[] = {
       { "all",  "All",        SRCH_ALL      },
       { "c",    "Check-ins",  SRCH_CKIN     },
       { "d",    "Docs",       SRCH_DOC      },
       { "t",    "Tickets",    SRCH_TKT      },
       { "w",    "Wiki",       SRCH_WIKI     },
       { "e",    "Tech Notes", SRCH_TECHNOTE },
................................................................................
    }else{
      @ <div class='searchResult'>
    }
    if( search_run_and_output(zPattern, srchFlags, fDebug)==0 ){
      @ <p class='searchEmpty'>No matches for: <span>%h(zPattern)</span></p>
    }
    @ </div>
    haveResult = 1;
  }
  return haveResult;
}

/*
** WEBPAGE: search
**
** Search for check-in comments, documents, tickets, or wiki that
** match a user-supplied pattern.