Fossil SCM

In /forum, when selecting a status filter clear out the x= hidden form field so that we return to the start of the list for the newly-selected status. This requires a JS-side solution. Just now discovered that it's not filtering quite properly when the explicitly-selected status is the default status and a post has a status=Z value for which Z is not in the configured status list. Per the agreed-upon rules, such posts should be treated as having the first/default status but they're currently being filtered out in that case.

stephan 2026-05-28 10:06 UTC forum-statuses
Commit d1fb4a49bb3418d2fc411a8b5259bdf44de517c443efc2495aa3f3f6c40756ed
--- src/forum.c
+++ src/forum.c
@@ -2499,10 +2499,14 @@
24992499
iStatusTagId, !!zStatusFilter, zStatusFilter
25002500
);
25012501
if( zStatusFilter ){
25022502
const int bIsDflt =
25032503
0==fossil_strcmp(pFstat->aStatus[0].zValue, zStatusFilter);
2504
+ const int bIsKnown =bIsDflt
2505
+ ? 1
2506
+ : db_int(0, "SELECT 1 FROM forumstatus WHERE value=%Q",
2507
+ zStatusFilter);
25042508
db_multi_exec(
25052509
"INSERT INTO trootid\n"
25062510
/* Rules:
25072511
25082512
(1) Filter on status=$zStatusFilter
@@ -2677,7 +2681,12 @@
26772681
if( iCnt>0 ){
26782682
@ </table></div>
26792683
}else{
26802684
@ <h1>No forum posts found</h1>
26812685
}
2686
+ if( bHasStatus ){
2687
+ /* We need a JS-side kludge to avoid passing on the x=N
2688
+ ** URL arg when the status selection list is activated. */
2689
+ forum_emit_js();
2690
+ }
26822691
style_finish_page();
26832692
}
26842693
--- src/forum.c
+++ src/forum.c
@@ -2499,10 +2499,14 @@
2499 iStatusTagId, !!zStatusFilter, zStatusFilter
2500 );
2501 if( zStatusFilter ){
2502 const int bIsDflt =
2503 0==fossil_strcmp(pFstat->aStatus[0].zValue, zStatusFilter);
 
 
 
 
2504 db_multi_exec(
2505 "INSERT INTO trootid\n"
2506 /* Rules:
2507
2508 (1) Filter on status=$zStatusFilter
@@ -2677,7 +2681,12 @@
2677 if( iCnt>0 ){
2678 @ </table></div>
2679 }else{
2680 @ <h1>No forum posts found</h1>
2681 }
 
 
 
 
 
2682 style_finish_page();
2683 }
2684
--- src/forum.c
+++ src/forum.c
@@ -2499,10 +2499,14 @@
2499 iStatusTagId, !!zStatusFilter, zStatusFilter
2500 );
2501 if( zStatusFilter ){
2502 const int bIsDflt =
2503 0==fossil_strcmp(pFstat->aStatus[0].zValue, zStatusFilter);
2504 const int bIsKnown =bIsDflt
2505 ? 1
2506 : db_int(0, "SELECT 1 FROM forumstatus WHERE value=%Q",
2507 zStatusFilter);
2508 db_multi_exec(
2509 "INSERT INTO trootid\n"
2510 /* Rules:
2511
2512 (1) Filter on status=$zStatusFilter
@@ -2677,7 +2681,12 @@
2681 if( iCnt>0 ){
2682 @ </table></div>
2683 }else{
2684 @ <h1>No forum posts found</h1>
2685 }
2686 if( bHasStatus ){
2687 /* We need a JS-side kludge to avoid passing on the x=N
2688 ** URL arg when the status selection list is activated. */
2689 forum_emit_js();
2690 }
2691 style_finish_page();
2692 }
2693
--- src/fossil.page.forumpost.js
+++ src/fossil.page.forumpost.js
@@ -94,71 +94,87 @@
9494
forumPostWrapper.appendChild(widget);
9595
}
9696
content.appendChild(rightTapZone);
9797
rightTapZone.addEventListener('click', widgetEventHandler, false);
9898
refillTapZone();
99
- })/*F.onPageLoad()*/;
99
+ })/*for-each div.forumTime|div.forumEdit*/;
100100
101101
if(F.pikchr){
102102
F.pikchr.addSrcView();
103103
}
104104
105
- /* Attempt to keep stray double-clicks from double-posting.
106
- https://fossil-scm.org/forum/info/6bd02466533aa131 */
107
- const formSubmitted = function(event){
108
- const form = event.target;
109
- if( form.dataset.submitted ){
110
- event.preventDefault();
111
- return;
112
- }
113
- form.dataset.submitted = '1';
114
- /** If the user is left waiting "a long time," disable the
115
- resubmit protection. If we don't do this and they tap the
116
- browser's cancel button while waiting, they'll be stuck with
117
- an unsubmittable form. */
118
- setTimeout(()=>{delete form.dataset.submitted}, 7000);
119
- return;
120
- };
121
- document.querySelectorAll("form").forEach(function(form){
122
- form.addEventListener('submit',formSubmitted);
123
- form
124
- .querySelectorAll("input.action-close, input.action-reopen")
125
- .forEach(function(e){
126
- e.classList.remove('hidden');
127
- F.confirmer(e, {
128
- confirmText: (e.classList.contains('action-reopen')
129
- ? "Confirm re-open"
130
- : "Confirm close"),
131
- onconfirm: ()=>form.submit()
132
- });
133
- });
134
- form
135
- .querySelectorAll("input[type='button'].action-status")
136
- .forEach(function(btn){
137
- btn.classList.remove('hidden');
138
- const sel = btn.previousElementSibling;
139
- const updateAble = ()=>{
140
- if( sel.dataset.initialValue ){
141
- if( sel.dataset.initialValue===sel.value ){
142
- btn.setAttribute('disabled','');
143
- }else{
144
- btn.removeAttribute('disabled');
145
- }
146
- }else{
147
- if(sel.selectedIndex===0){
148
- btn.setAttribute('disabled','');
149
- }else{
150
- btn.removeAttribute('disabled');
151
- }
152
- }
153
- };
154
- sel.addEventListener('change', updateAble, true);
155
- updateAble();
156
- F.confirmer(btn, {
157
- confirmText: "Confirm status change",
158
- onconfirm: ()=>form.submit()
159
- });
160
- });
161
- });
105
+ const eStatus = document.querySelector(
106
+ 'form div.submenu select.submenuctrl[name="status"]'
107
+ );
108
+ if( eStatus ){
109
+ /* Main /forum list. Remove the 'x' form element when eStatus
110
+ ** changes, to avoid propagating x when changing the filter. */
111
+ const pForm = eStatus.parentElement?.parentElement;
112
+ if( pForm ){
113
+ eStatus.addEventListener('change', ()=>{
114
+ pForm.querySelector('input[type="hidden"][name="x"]')?.remove();
115
+ }, true);
116
+ }
117
+ }else{
118
+ /* One of the single-post edit/view pages. Handle various UI
119
+ controls and attempt to keep stray double-clicks from
120
+ double-posting.
121
+ https://fossil-scm.org/forum/info/6bd02466533aa131 */
122
+ const formSubmitted = function(event){
123
+ const form = event.target;
124
+ if( form.dataset.submitted ){
125
+ event.preventDefault();
126
+ return;
127
+ }
128
+ form.dataset.submitted = '1';
129
+ /** If the user is left waiting "a long time," disable the
130
+ resubmit protection. If we don't do this and they tap the
131
+ browser's cancel button while waiting, they'll be stuck with
132
+ an unsubmittable form. */
133
+ setTimeout(()=>{delete form.dataset.submitted}, 7000);
134
+ return;
135
+ };
136
+ document.querySelectorAll("form").forEach(function(form){
137
+ form.addEventListener('submit', formSubmitted);
138
+ form
139
+ .querySelectorAll("input.action-close, input.action-reopen")
140
+ .forEach(function(e){
141
+ e.classList.remove('hidden');
142
+ F.confirmer(e, {
143
+ confirmText: (e.classList.contains('action-reopen')
144
+ ? "Confirm re-open"
145
+ : "Confirm close"),
146
+ onconfirm: ()=>form.submit()
147
+ });
148
+ });
149
+ form
150
+ .querySelectorAll("input[type='button'].action-status")
151
+ .forEach(function(btn){
152
+ btn.classList.remove('hidden');
153
+ const sel = btn.previousElementSibling;
154
+ const updateAble = ()=>{
155
+ if( sel.dataset.initialValue ){
156
+ if( sel.dataset.initialValue===sel.value ){
157
+ btn.setAttribute('disabled','');
158
+ }else{
159
+ btn.removeAttribute('disabled');
160
+ }
161
+ }else{
162
+ if(sel.selectedIndex===0){
163
+ btn.setAttribute('disabled','');
164
+ }else{
165
+ btn.removeAttribute('disabled');
166
+ }
167
+ }
168
+ };
169
+ sel.addEventListener('change', updateAble, true);
170
+ updateAble();
171
+ F.confirmer(btn, {
172
+ confirmText: "Confirm status change",
173
+ onconfirm: ()=>form.submit()
174
+ });
175
+ });
176
+ });
177
+ }
162178
163179
})/*F.onPageLoad callback*/;
164180
})(window.fossil);
165181
--- src/fossil.page.forumpost.js
+++ src/fossil.page.forumpost.js
@@ -94,71 +94,87 @@
94 forumPostWrapper.appendChild(widget);
95 }
96 content.appendChild(rightTapZone);
97 rightTapZone.addEventListener('click', widgetEventHandler, false);
98 refillTapZone();
99 })/*F.onPageLoad()*/;
100
101 if(F.pikchr){
102 F.pikchr.addSrcView();
103 }
104
105 /* Attempt to keep stray double-clicks from double-posting.
106 https://fossil-scm.org/forum/info/6bd02466533aa131 */
107 const formSubmitted = function(event){
108 const form = event.target;
109 if( form.dataset.submitted ){
110 event.preventDefault();
111 return;
112 }
113 form.dataset.submitted = '1';
114 /** If the user is left waiting "a long time," disable the
115 resubmit protection. If we don't do this and they tap the
116 browser's cancel button while waiting, they'll be stuck with
117 an unsubmittable form. */
118 setTimeout(()=>{delete form.dataset.submitted}, 7000);
119 return;
120 };
121 document.querySelectorAll("form").forEach(function(form){
122 form.addEventListener('submit',formSubmitted);
123 form
124 .querySelectorAll("input.action-close, input.action-reopen")
125 .forEach(function(e){
126 e.classList.remove('hidden');
127 F.confirmer(e, {
128 confirmText: (e.classList.contains('action-reopen')
129 ? "Confirm re-open"
130 : "Confirm close"),
131 onconfirm: ()=>form.submit()
132 });
133 });
134 form
135 .querySelectorAll("input[type='button'].action-status")
136 .forEach(function(btn){
137 btn.classList.remove('hidden');
138 const sel = btn.previousElementSibling;
139 const updateAble = ()=>{
140 if( sel.dataset.initialValue ){
141 if( sel.dataset.initialValue===sel.value ){
142 btn.setAttribute('disabled','');
143 }else{
144 btn.removeAttribute('disabled');
145 }
146 }else{
147 if(sel.selectedIndex===0){
148 btn.setAttribute('disabled','');
149 }else{
150 btn.removeAttribute('disabled');
151 }
152 }
153 };
154 sel.addEventListener('change', updateAble, true);
155 updateAble();
156 F.confirmer(btn, {
157 confirmText: "Confirm status change",
158 onconfirm: ()=>form.submit()
159 });
160 });
161 });
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
162
163 })/*F.onPageLoad callback*/;
164 })(window.fossil);
165
--- src/fossil.page.forumpost.js
+++ src/fossil.page.forumpost.js
@@ -94,71 +94,87 @@
94 forumPostWrapper.appendChild(widget);
95 }
96 content.appendChild(rightTapZone);
97 rightTapZone.addEventListener('click', widgetEventHandler, false);
98 refillTapZone();
99 })/*for-each div.forumTime|div.forumEdit*/;
100
101 if(F.pikchr){
102 F.pikchr.addSrcView();
103 }
104
105 const eStatus = document.querySelector(
106 'form div.submenu select.submenuctrl[name="status"]'
107 );
108 if( eStatus ){
109 /* Main /forum list. Remove the 'x' form element when eStatus
110 ** changes, to avoid propagating x when changing the filter. */
111 const pForm = eStatus.parentElement?.parentElement;
112 if( pForm ){
113 eStatus.addEventListener('change', ()=>{
114 pForm.querySelector('input[type="hidden"][name="x"]')?.remove();
115 }, true);
116 }
117 }else{
118 /* One of the single-post edit/view pages. Handle various UI
119 controls and attempt to keep stray double-clicks from
120 double-posting.
121 https://fossil-scm.org/forum/info/6bd02466533aa131 */
122 const formSubmitted = function(event){
123 const form = event.target;
124 if( form.dataset.submitted ){
125 event.preventDefault();
126 return;
127 }
128 form.dataset.submitted = '1';
129 /** If the user is left waiting "a long time," disable the
130 resubmit protection. If we don't do this and they tap the
131 browser's cancel button while waiting, they'll be stuck with
132 an unsubmittable form. */
133 setTimeout(()=>{delete form.dataset.submitted}, 7000);
134 return;
135 };
136 document.querySelectorAll("form").forEach(function(form){
137 form.addEventListener('submit', formSubmitted);
138 form
139 .querySelectorAll("input.action-close, input.action-reopen")
140 .forEach(function(e){
141 e.classList.remove('hidden');
142 F.confirmer(e, {
143 confirmText: (e.classList.contains('action-reopen')
144 ? "Confirm re-open"
145 : "Confirm close"),
146 onconfirm: ()=>form.submit()
147 });
148 });
149 form
150 .querySelectorAll("input[type='button'].action-status")
151 .forEach(function(btn){
152 btn.classList.remove('hidden');
153 const sel = btn.previousElementSibling;
154 const updateAble = ()=>{
155 if( sel.dataset.initialValue ){
156 if( sel.dataset.initialValue===sel.value ){
157 btn.setAttribute('disabled','');
158 }else{
159 btn.removeAttribute('disabled');
160 }
161 }else{
162 if(sel.selectedIndex===0){
163 btn.setAttribute('disabled','');
164 }else{
165 btn.removeAttribute('disabled');
166 }
167 }
168 };
169 sel.addEventListener('change', updateAble, true);
170 updateAble();
171 F.confirmer(btn, {
172 confirmText: "Confirm status change",
173 onconfirm: ()=>form.submit()
174 });
175 });
176 });
177 }
178
179 })/*F.onPageLoad callback*/;
180 })(window.fossil);
181

Keyboard Shortcuts

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