Fossil SCM

Initial sketches for the ability to assign a status=X tag to forum posts, e.g. opened vs resolved. This compiles but does nothing useful.

stephan 2026-05-25 13:05 UTC trunk
Commit 025256542f00e1b3e12da50bb148a57c97ab930b5857185b9029289172364c11
2 files changed +1 +75 -2
--- src/configure.c
+++ src/configure.c
@@ -143,10 +143,11 @@
143143
{ "hash-policy", CONFIGSET_PROJ },
144144
{ "comment-format", CONFIGSET_PROJ },
145145
{ "mimetypes", CONFIGSET_PROJ },
146146
{ "forbid-delta-manifests", CONFIGSET_PROJ },
147147
{ "mv-rm-files", CONFIGSET_PROJ },
148
+ { "forum-statuses", CONFIGSET_PROJ },
148149
{ "ticket-table", CONFIGSET_TKT },
149150
{ "ticket-common", CONFIGSET_TKT },
150151
{ "ticket-change", CONFIGSET_TKT },
151152
{ "ticket-newpage", CONFIGSET_TKT },
152153
{ "ticket-viewpage", CONFIGSET_TKT },
153154
--- src/configure.c
+++ src/configure.c
@@ -143,10 +143,11 @@
143 { "hash-policy", CONFIGSET_PROJ },
144 { "comment-format", CONFIGSET_PROJ },
145 { "mimetypes", CONFIGSET_PROJ },
146 { "forbid-delta-manifests", CONFIGSET_PROJ },
147 { "mv-rm-files", CONFIGSET_PROJ },
 
148 { "ticket-table", CONFIGSET_TKT },
149 { "ticket-common", CONFIGSET_TKT },
150 { "ticket-change", CONFIGSET_TKT },
151 { "ticket-newpage", CONFIGSET_TKT },
152 { "ticket-viewpage", CONFIGSET_TKT },
153
--- src/configure.c
+++ src/configure.c
@@ -143,10 +143,11 @@
143 { "hash-policy", CONFIGSET_PROJ },
144 { "comment-format", CONFIGSET_PROJ },
145 { "mimetypes", CONFIGSET_PROJ },
146 { "forbid-delta-manifests", CONFIGSET_PROJ },
147 { "mv-rm-files", CONFIGSET_PROJ },
148 { "forum-statuses", CONFIGSET_PROJ },
149 { "ticket-table", CONFIGSET_TKT },
150 { "ticket-common", CONFIGSET_TKT },
151 { "ticket-change", CONFIGSET_TKT },
152 { "ticket-newpage", CONFIGSET_TKT },
153 { "ticket-viewpage", CONFIGSET_TKT },
154
+75 -2
--- src/forum.c
+++ src/forum.c
@@ -61,11 +61,73 @@
6161
ForumPost *pDisplay; /* Entries in display order */
6262
ForumPost *pTail; /* Last on the display list */
6363
int mxIndent; /* Maximum indentation level */
6464
int nArtifact; /* Number of forum artifacts in this thread */
6565
};
66
+
67
+/*
68
+** A single entry from the forum-statuses setting.
69
+*/
70
+struct ForumStatus {
71
+ char *zValue; /* status=X tag value */
72
+ char *zLabel; /* Label for the UI */
73
+ char *zDescr; /* Brief description */
74
+};
75
+
76
+/*
77
+** A list of ForumStatus objects.
78
+*/
79
+struct ForumStatusList {
80
+ struct ForumStatus * aStatus; /* List of statuses */
81
+ unsigned int n; /* Number of entries */
82
+};
6683
#endif /* INTERFACE */
84
+
85
+/*
86
+** Returns a high-level representation of the forum-statuses setting.
87
+** This is a singleton, cached across calls.
88
+ */
89
+static const ForumStatusList * forum_statuses(void){
90
+ static ForumStatusList fses = {0,0};
91
+ static int once = 0;
92
+ if( !once ){
93
+ ++once;
94
+ /* TODO: read `forum-statuses` setting and transform it into the
95
+ ** fses object.
96
+ **
97
+ ** Maybe: if it's empty, synthesize a length-1 list from
98
+ ** {value:"default",label:"Default",...}. It's expected that
99
+ ** usage may be slightly simplified if we always have a non-empty
100
+ ** list. A length-1 list is, for purposes of the UI, identical to
101
+ ** an empty one - we cannot change statuses if there's only one
102
+ ** choice. */
103
+ }
104
+ return &fses;
105
+}
106
+
107
+/*
108
+** Search for a ForumStatus object by its tag value. If a match is
109
+** found, the corresponding object is returned. If no match is found
110
+** then (A) if bFirst is false then 0 is returned, else (B) the first
111
+** entry in the list is returned, noting that the list may be empty,
112
+** in which case 0 is returned.
113
+*/
114
+const ForumStatus * forum_status_by_value(const char *z, int bFirst){
115
+ const ForumStatusList * const fses = forum_statuses();
116
+ const ForumStatus * fs0 = 0;
117
+ unsigned int i;
118
+ if( !fses->n ) return 0;
119
+ for( i = 0; i < fses->n; ++i ){
120
+ const ForumStatus * fs = &fses->aStatus[i];
121
+ if( 0==fossil_strcmp(z, fs->zValue) ){
122
+ return fs;
123
+ }else if( !fs0 ){
124
+ fs0 = fs;
125
+ }
126
+ }
127
+ return bFirst ? fs0 : 0;
128
+}
67129
68130
/*
69131
** Return true if the forum post with the given rid has been
70132
** subsequently edited.
71133
*/
@@ -174,12 +236,12 @@
174236
** - 0 if no matching tag is found.
175237
**
176238
** - The tagxref.rowid of the tagxref entry for the closure if rid is
177239
** the forum post to which the closure applies.
178240
**
179
-** - (-tagxref.rowid) if the given rid inherits a "closed" tag from an
180
-** IRT forum post.
241
+** - (-tagxref.rowid) if the given rid inherits the tag from an IRT
242
+** forum post.
181243
*/
182244
static int forum_rid_is_tagged(int rid, const char *zTagName, int bCheckIrt){
183245
static Stmt qIrt = empty_Stmt_m;
184246
int rc = 0, i = 0;
185247
/* TODO: this can probably be turned into a CTE by someone with
@@ -1968,10 +2030,21 @@
19682030
** seems more appropriate for the particular usage.
19692031
**
19702032
** SETTING: attachment-size-limit width=16
19712033
** The maximum number of bytes for an attachment. The default (or 0) is
19722034
** unlimited but a limit may be imposed by the web server or a proxy.
2035
+**
2036
+** SETTING: forum-statuses width=40 block-text
2037
+** This JSON5-formatted value defines an array of objects describing
2038
+** the available statuses of forum posts. Each entry of the array must
2039
+** be an object in the form {label:"X",value:"Y",description:"Z"}.
2040
+** The label is used in the UI and value becomes the value of the
2041
+** "status" tag on forum posts. Any forum post which has a status
2042
+** value which does not appear in this list is treated as if it had
2043
+** the first value from this list. If this setting is empty, is
2044
+** ill-formed JSON, or has only a single entry then the forum will
2045
+** lack the capability of setting and filtering by status.
19732046
*/
19742047
19752048
/*
19762049
** WEBPAGE: setup_forum
19772050
**
19782051
--- src/forum.c
+++ src/forum.c
@@ -61,11 +61,73 @@
61 ForumPost *pDisplay; /* Entries in display order */
62 ForumPost *pTail; /* Last on the display list */
63 int mxIndent; /* Maximum indentation level */
64 int nArtifact; /* Number of forum artifacts in this thread */
65 };
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
66 #endif /* INTERFACE */
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
67
68 /*
69 ** Return true if the forum post with the given rid has been
70 ** subsequently edited.
71 */
@@ -174,12 +236,12 @@
174 ** - 0 if no matching tag is found.
175 **
176 ** - The tagxref.rowid of the tagxref entry for the closure if rid is
177 ** the forum post to which the closure applies.
178 **
179 ** - (-tagxref.rowid) if the given rid inherits a "closed" tag from an
180 ** IRT forum post.
181 */
182 static int forum_rid_is_tagged(int rid, const char *zTagName, int bCheckIrt){
183 static Stmt qIrt = empty_Stmt_m;
184 int rc = 0, i = 0;
185 /* TODO: this can probably be turned into a CTE by someone with
@@ -1968,10 +2030,21 @@
1968 ** seems more appropriate for the particular usage.
1969 **
1970 ** SETTING: attachment-size-limit width=16
1971 ** The maximum number of bytes for an attachment. The default (or 0) is
1972 ** unlimited but a limit may be imposed by the web server or a proxy.
 
 
 
 
 
 
 
 
 
 
 
1973 */
1974
1975 /*
1976 ** WEBPAGE: setup_forum
1977 **
1978
--- src/forum.c
+++ src/forum.c
@@ -61,11 +61,73 @@
61 ForumPost *pDisplay; /* Entries in display order */
62 ForumPost *pTail; /* Last on the display list */
63 int mxIndent; /* Maximum indentation level */
64 int nArtifact; /* Number of forum artifacts in this thread */
65 };
66
67 /*
68 ** A single entry from the forum-statuses setting.
69 */
70 struct ForumStatus {
71 char *zValue; /* status=X tag value */
72 char *zLabel; /* Label for the UI */
73 char *zDescr; /* Brief description */
74 };
75
76 /*
77 ** A list of ForumStatus objects.
78 */
79 struct ForumStatusList {
80 struct ForumStatus * aStatus; /* List of statuses */
81 unsigned int n; /* Number of entries */
82 };
83 #endif /* INTERFACE */
84
85 /*
86 ** Returns a high-level representation of the forum-statuses setting.
87 ** This is a singleton, cached across calls.
88 */
89 static const ForumStatusList * forum_statuses(void){
90 static ForumStatusList fses = {0,0};
91 static int once = 0;
92 if( !once ){
93 ++once;
94 /* TODO: read `forum-statuses` setting and transform it into the
95 ** fses object.
96 **
97 ** Maybe: if it's empty, synthesize a length-1 list from
98 ** {value:"default",label:"Default",...}. It's expected that
99 ** usage may be slightly simplified if we always have a non-empty
100 ** list. A length-1 list is, for purposes of the UI, identical to
101 ** an empty one - we cannot change statuses if there's only one
102 ** choice. */
103 }
104 return &fses;
105 }
106
107 /*
108 ** Search for a ForumStatus object by its tag value. If a match is
109 ** found, the corresponding object is returned. If no match is found
110 ** then (A) if bFirst is false then 0 is returned, else (B) the first
111 ** entry in the list is returned, noting that the list may be empty,
112 ** in which case 0 is returned.
113 */
114 const ForumStatus * forum_status_by_value(const char *z, int bFirst){
115 const ForumStatusList * const fses = forum_statuses();
116 const ForumStatus * fs0 = 0;
117 unsigned int i;
118 if( !fses->n ) return 0;
119 for( i = 0; i < fses->n; ++i ){
120 const ForumStatus * fs = &fses->aStatus[i];
121 if( 0==fossil_strcmp(z, fs->zValue) ){
122 return fs;
123 }else if( !fs0 ){
124 fs0 = fs;
125 }
126 }
127 return bFirst ? fs0 : 0;
128 }
129
130 /*
131 ** Return true if the forum post with the given rid has been
132 ** subsequently edited.
133 */
@@ -174,12 +236,12 @@
236 ** - 0 if no matching tag is found.
237 **
238 ** - The tagxref.rowid of the tagxref entry for the closure if rid is
239 ** the forum post to which the closure applies.
240 **
241 ** - (-tagxref.rowid) if the given rid inherits the tag from an IRT
242 ** forum post.
243 */
244 static int forum_rid_is_tagged(int rid, const char *zTagName, int bCheckIrt){
245 static Stmt qIrt = empty_Stmt_m;
246 int rc = 0, i = 0;
247 /* TODO: this can probably be turned into a CTE by someone with
@@ -1968,10 +2030,21 @@
2030 ** seems more appropriate for the particular usage.
2031 **
2032 ** SETTING: attachment-size-limit width=16
2033 ** The maximum number of bytes for an attachment. The default (or 0) is
2034 ** unlimited but a limit may be imposed by the web server or a proxy.
2035 **
2036 ** SETTING: forum-statuses width=40 block-text
2037 ** This JSON5-formatted value defines an array of objects describing
2038 ** the available statuses of forum posts. Each entry of the array must
2039 ** be an object in the form {label:"X",value:"Y",description:"Z"}.
2040 ** The label is used in the UI and value becomes the value of the
2041 ** "status" tag on forum posts. Any forum post which has a status
2042 ** value which does not appear in this list is treated as if it had
2043 ** the first value from this list. If this setting is empty, is
2044 ** ill-formed JSON, or has only a single entry then the forum will
2045 ** lack the capability of setting and filtering by status.
2046 */
2047
2048 /*
2049 ** WEBPAGE: setup_forum
2050 **
2051

Keyboard Shortcuts

Open search /
Next entry (timeline) j
Previous entry (timeline) k
Open focused entry Enter
Show this help ?
Toggle theme Top nav button