Fossil SCM
Re-enable the forum post status selection in the editor since the previous check-in made it safe to use, in that changing only the status from the editor will no longer create a new copy of an otherwise unedited post.
Commit
0f539c6c29f090dabc2f8a1717a66eeae710be93c4c13b1a6a4005433b2c32ac
Parent
ab52bc833121dcc…
1 file changed
+17
-24
+17
-24
| --- src/fossil.page.forumpost.js | ||
| +++ src/fossil.page.forumpost.js | ||
| @@ -37,11 +37,12 @@ | ||
| 37 | 37 | Options: |
| 38 | 38 | |
| 39 | 39 | opt.draftKey[string=undefined]: if set then this object's state |
| 40 | 40 | will be stored in fossil.storage when the relevant input fields |
| 41 | 41 | lose focus. If old state is found, the form is pre-populated |
| 42 | - from it. The state is cleared on a successful submit. | |
| 42 | + from it. The state is cleared on a discard() or successful | |
| 43 | + submit. | |
| 43 | 44 | |
| 44 | 45 | opt.ondiscard[=function]: if set, a Discard button is added |
| 45 | 46 | which, when activated, clears the current draft and removes |
| 46 | 47 | this object's widget from the DOM. After doing so, |
| 47 | 48 | opt.ondiscard() is called and passed no arguments. Exceptions |
| @@ -48,14 +49,12 @@ | ||
| 48 | 49 | thrown by ondiscard() are ignored but may be logged. |
| 49 | 50 | |
| 50 | 51 | opt.onsubmit[=function]: if set, this function is called |
| 51 | 52 | immediately after the post has been successfully saved, and |
| 52 | 53 | passed this object and a JSON-format response object from the |
| 53 | - save request. On a successful edit, if the artifact was | |
| 54 | - actually modified then submission will redirect the page to | |
| 55 | - /forumpost/THE_POST_ID. Exceptions thrown by onsubmit() | |
| 56 | - are ignored but may be logged. | |
| 54 | + save request. It is generally then up to the caller to close() | |
| 55 | + this object and/or redirect to /forumpost/${arguments[1].uuid}. | |
| 57 | 56 | |
| 58 | 57 | opt.hiddenFields: an optional list of input elements to |
| 59 | 58 | incorporate into the form for requests which request the |
| 60 | 59 | preview or save the post. |
| 61 | 60 | |
| @@ -257,24 +256,13 @@ | ||
| 257 | 256 | } |
| 258 | 257 | this.#tabs.addTab(e.debug); |
| 259 | 258 | } |
| 260 | 259 | e.buttons.append(e.mimetype.wrapper); |
| 261 | 260 | |
| 262 | - if( 0 /* 2026-06-09: disabling the status selection to keep | |
| 263 | - people from using the editor to change just that, | |
| 264 | - because doing so leaves us in a staet where we know | |
| 265 | - whether or not a Submit modifies the post, but not | |
| 266 | - whether or not out-of-band state like the status and | |
| 267 | - attachments were modified. */ | |
| 268 | - && opt.edit | |
| 261 | + if( opt.edit | |
| 269 | 262 | && !opt.inReplyTo |
| 270 | 263 | && F.config.forumStatuses?.length>0 ){ |
| 271 | - /* Status selection. We probably don't _really_ want this in | |
| 272 | - the editor because people will open the editor, change the | |
| 273 | - status, and tap submit, resulting in a whole new, unedited | |
| 274 | - copy of the post, differing only in the new 'status' tag | |
| 275 | - added to it. */ | |
| 276 | 264 | const sel = e.status = D.select(); |
| 277 | 265 | D.option(sel, "", "- Status -").disabled = true; |
| 278 | 266 | for( const status of F.config.forumStatuses ){ |
| 279 | 267 | D.option(sel, status.value, status.label); |
| 280 | 268 | } |
| @@ -696,11 +684,11 @@ | ||
| 696 | 684 | reload to render those changes (if any). The other option |
| 697 | 685 | is to tell the user "nothing changed" and leave them in |
| 698 | 686 | the editor, but that could be a lie because we don't know |
| 699 | 687 | if any attachments or tags were changed. |
| 700 | 688 | */ |
| 701 | - if( 0 ){ | |
| 689 | + else if( 0 ){ | |
| 702 | 690 | if( this.#opt.edit.uuid === j.uuid |
| 703 | 691 | && !j.statusModified && 0===j.attachedCount ){ |
| 704 | 692 | this.reportError("No changes made."); |
| 705 | 693 | }else{ |
| 706 | 694 | window.location = F.repoUrl('forumpost/'+j.uuid); |
| @@ -971,12 +959,12 @@ | ||
| 971 | 959 | draftKey: 'draft-forumnew', |
| 972 | 960 | hiddenFields: eForumNew.querySelectorAll('input[type=hidden]'), |
| 973 | 961 | ondiscard: ()=>{ |
| 974 | 962 | window.location = F.repoUrl('forum'); |
| 975 | 963 | }, |
| 976 | - onsubmit: (fpe, artifact)=>{ | |
| 977 | - window.location = F.repoUrl('forumpost/'+artifact.uuid); | |
| 964 | + onsubmit: (fpe, response)=>{ | |
| 965 | + window.location = F.repoUrl('forumpost/'+response.uuid); | |
| 978 | 966 | } |
| 979 | 967 | }); |
| 980 | 968 | eForumNew.parentElement.insertBefore(fpe.widget, eForumNew); |
| 981 | 969 | eForumNew.remove(); |
| 982 | 970 | fossil.page.fpe = fpe /* for testing via the console */; |
| @@ -1083,11 +1071,11 @@ | ||
| 1083 | 1071 | hiddenFields: form.querySelectorAll('input[type=hidden]'), |
| 1084 | 1072 | ondiscard: ondone, |
| 1085 | 1073 | onsubmit: ondone, |
| 1086 | 1074 | draftKey: 'draft-forumedit-'+(fEditHead || fpid).substr(0,12), |
| 1087 | 1075 | edit: artifact, |
| 1088 | - //status: eStatusSelect?.value, | |
| 1076 | + status: eStatusSelect?.value, | |
| 1089 | 1077 | inReplyTo: firt |
| 1090 | 1078 | }); |
| 1091 | 1079 | initFPEWidget(ePost, fpe); |
| 1092 | 1080 | }); |
| 1093 | 1081 | }/*editClicked()*/; |
| @@ -1094,19 +1082,24 @@ | ||
| 1094 | 1082 | |
| 1095 | 1083 | document.body.querySelectorAll( |
| 1096 | 1084 | '.forumpost-single-controls > form' |
| 1097 | 1085 | ).forEach(form=>{ |
| 1098 | 1086 | /* For each forum post... */ |
| 1099 | - const eToDisable = []; | |
| 1100 | - const eThePost = form.parentElement.parentElement; | |
| 1087 | + const eToDisable = [ | |
| 1088 | + /* List of non-editor DOM elements which need to be disabled | |
| 1089 | + when the editor is active. */ | |
| 1090 | + ]; | |
| 1091 | + const eThePost = form.parentElement.parentElement/*main post DOM element*/; | |
| 1101 | 1092 | if( !eThePost?.dataset?.fpid ){ |
| 1093 | + /* The server injects these. */ | |
| 1102 | 1094 | console.warn("Unexpected missing fpid", eThePost); |
| 1103 | 1095 | return; |
| 1104 | 1096 | } |
| 1097 | + /* Replace the Reply and Edit buttons with ones which will activate | |
| 1098 | + a ForumPostEditor. */ | |
| 1105 | 1099 | const btnReply = form.querySelector('input[type=submit][name=reply]'); |
| 1106 | 1100 | if( btnReply ){ |
| 1107 | - //console.debug("hacking Reply button", btnReply); | |
| 1108 | 1101 | const b = D.button("Reply", ()=>replyClicked(form, eThePost, b, eToDisable)); |
| 1109 | 1102 | b.type = 'button'/*keep container form from submitting*/; |
| 1110 | 1103 | eToDisable.push(b); |
| 1111 | 1104 | btnReply.parentElement.insertBefore(b, btnReply); |
| 1112 | 1105 | btnReply.remove(); |
| 1113 | 1106 |
| --- src/fossil.page.forumpost.js | |
| +++ src/fossil.page.forumpost.js | |
| @@ -37,11 +37,12 @@ | |
| 37 | Options: |
| 38 | |
| 39 | opt.draftKey[string=undefined]: if set then this object's state |
| 40 | will be stored in fossil.storage when the relevant input fields |
| 41 | lose focus. If old state is found, the form is pre-populated |
| 42 | from it. The state is cleared on a successful submit. |
| 43 | |
| 44 | opt.ondiscard[=function]: if set, a Discard button is added |
| 45 | which, when activated, clears the current draft and removes |
| 46 | this object's widget from the DOM. After doing so, |
| 47 | opt.ondiscard() is called and passed no arguments. Exceptions |
| @@ -48,14 +49,12 @@ | |
| 48 | thrown by ondiscard() are ignored but may be logged. |
| 49 | |
| 50 | opt.onsubmit[=function]: if set, this function is called |
| 51 | immediately after the post has been successfully saved, and |
| 52 | passed this object and a JSON-format response object from the |
| 53 | save request. On a successful edit, if the artifact was |
| 54 | actually modified then submission will redirect the page to |
| 55 | /forumpost/THE_POST_ID. Exceptions thrown by onsubmit() |
| 56 | are ignored but may be logged. |
| 57 | |
| 58 | opt.hiddenFields: an optional list of input elements to |
| 59 | incorporate into the form for requests which request the |
| 60 | preview or save the post. |
| 61 | |
| @@ -257,24 +256,13 @@ | |
| 257 | } |
| 258 | this.#tabs.addTab(e.debug); |
| 259 | } |
| 260 | e.buttons.append(e.mimetype.wrapper); |
| 261 | |
| 262 | if( 0 /* 2026-06-09: disabling the status selection to keep |
| 263 | people from using the editor to change just that, |
| 264 | because doing so leaves us in a staet where we know |
| 265 | whether or not a Submit modifies the post, but not |
| 266 | whether or not out-of-band state like the status and |
| 267 | attachments were modified. */ |
| 268 | && opt.edit |
| 269 | && !opt.inReplyTo |
| 270 | && F.config.forumStatuses?.length>0 ){ |
| 271 | /* Status selection. We probably don't _really_ want this in |
| 272 | the editor because people will open the editor, change the |
| 273 | status, and tap submit, resulting in a whole new, unedited |
| 274 | copy of the post, differing only in the new 'status' tag |
| 275 | added to it. */ |
| 276 | const sel = e.status = D.select(); |
| 277 | D.option(sel, "", "- Status -").disabled = true; |
| 278 | for( const status of F.config.forumStatuses ){ |
| 279 | D.option(sel, status.value, status.label); |
| 280 | } |
| @@ -696,11 +684,11 @@ | |
| 696 | reload to render those changes (if any). The other option |
| 697 | is to tell the user "nothing changed" and leave them in |
| 698 | the editor, but that could be a lie because we don't know |
| 699 | if any attachments or tags were changed. |
| 700 | */ |
| 701 | if( 0 ){ |
| 702 | if( this.#opt.edit.uuid === j.uuid |
| 703 | && !j.statusModified && 0===j.attachedCount ){ |
| 704 | this.reportError("No changes made."); |
| 705 | }else{ |
| 706 | window.location = F.repoUrl('forumpost/'+j.uuid); |
| @@ -971,12 +959,12 @@ | |
| 971 | draftKey: 'draft-forumnew', |
| 972 | hiddenFields: eForumNew.querySelectorAll('input[type=hidden]'), |
| 973 | ondiscard: ()=>{ |
| 974 | window.location = F.repoUrl('forum'); |
| 975 | }, |
| 976 | onsubmit: (fpe, artifact)=>{ |
| 977 | window.location = F.repoUrl('forumpost/'+artifact.uuid); |
| 978 | } |
| 979 | }); |
| 980 | eForumNew.parentElement.insertBefore(fpe.widget, eForumNew); |
| 981 | eForumNew.remove(); |
| 982 | fossil.page.fpe = fpe /* for testing via the console */; |
| @@ -1083,11 +1071,11 @@ | |
| 1083 | hiddenFields: form.querySelectorAll('input[type=hidden]'), |
| 1084 | ondiscard: ondone, |
| 1085 | onsubmit: ondone, |
| 1086 | draftKey: 'draft-forumedit-'+(fEditHead || fpid).substr(0,12), |
| 1087 | edit: artifact, |
| 1088 | //status: eStatusSelect?.value, |
| 1089 | inReplyTo: firt |
| 1090 | }); |
| 1091 | initFPEWidget(ePost, fpe); |
| 1092 | }); |
| 1093 | }/*editClicked()*/; |
| @@ -1094,19 +1082,24 @@ | |
| 1094 | |
| 1095 | document.body.querySelectorAll( |
| 1096 | '.forumpost-single-controls > form' |
| 1097 | ).forEach(form=>{ |
| 1098 | /* For each forum post... */ |
| 1099 | const eToDisable = []; |
| 1100 | const eThePost = form.parentElement.parentElement; |
| 1101 | if( !eThePost?.dataset?.fpid ){ |
| 1102 | console.warn("Unexpected missing fpid", eThePost); |
| 1103 | return; |
| 1104 | } |
| 1105 | const btnReply = form.querySelector('input[type=submit][name=reply]'); |
| 1106 | if( btnReply ){ |
| 1107 | //console.debug("hacking Reply button", btnReply); |
| 1108 | const b = D.button("Reply", ()=>replyClicked(form, eThePost, b, eToDisable)); |
| 1109 | b.type = 'button'/*keep container form from submitting*/; |
| 1110 | eToDisable.push(b); |
| 1111 | btnReply.parentElement.insertBefore(b, btnReply); |
| 1112 | btnReply.remove(); |
| 1113 |
| --- src/fossil.page.forumpost.js | |
| +++ src/fossil.page.forumpost.js | |
| @@ -37,11 +37,12 @@ | |
| 37 | Options: |
| 38 | |
| 39 | opt.draftKey[string=undefined]: if set then this object's state |
| 40 | will be stored in fossil.storage when the relevant input fields |
| 41 | lose focus. If old state is found, the form is pre-populated |
| 42 | from it. The state is cleared on a discard() or successful |
| 43 | submit. |
| 44 | |
| 45 | opt.ondiscard[=function]: if set, a Discard button is added |
| 46 | which, when activated, clears the current draft and removes |
| 47 | this object's widget from the DOM. After doing so, |
| 48 | opt.ondiscard() is called and passed no arguments. Exceptions |
| @@ -48,14 +49,12 @@ | |
| 49 | thrown by ondiscard() are ignored but may be logged. |
| 50 | |
| 51 | opt.onsubmit[=function]: if set, this function is called |
| 52 | immediately after the post has been successfully saved, and |
| 53 | passed this object and a JSON-format response object from the |
| 54 | save request. It is generally then up to the caller to close() |
| 55 | this object and/or redirect to /forumpost/${arguments[1].uuid}. |
| 56 | |
| 57 | opt.hiddenFields: an optional list of input elements to |
| 58 | incorporate into the form for requests which request the |
| 59 | preview or save the post. |
| 60 | |
| @@ -257,24 +256,13 @@ | |
| 256 | } |
| 257 | this.#tabs.addTab(e.debug); |
| 258 | } |
| 259 | e.buttons.append(e.mimetype.wrapper); |
| 260 | |
| 261 | if( opt.edit |
| 262 | && !opt.inReplyTo |
| 263 | && F.config.forumStatuses?.length>0 ){ |
| 264 | const sel = e.status = D.select(); |
| 265 | D.option(sel, "", "- Status -").disabled = true; |
| 266 | for( const status of F.config.forumStatuses ){ |
| 267 | D.option(sel, status.value, status.label); |
| 268 | } |
| @@ -696,11 +684,11 @@ | |
| 684 | reload to render those changes (if any). The other option |
| 685 | is to tell the user "nothing changed" and leave them in |
| 686 | the editor, but that could be a lie because we don't know |
| 687 | if any attachments or tags were changed. |
| 688 | */ |
| 689 | else if( 0 ){ |
| 690 | if( this.#opt.edit.uuid === j.uuid |
| 691 | && !j.statusModified && 0===j.attachedCount ){ |
| 692 | this.reportError("No changes made."); |
| 693 | }else{ |
| 694 | window.location = F.repoUrl('forumpost/'+j.uuid); |
| @@ -971,12 +959,12 @@ | |
| 959 | draftKey: 'draft-forumnew', |
| 960 | hiddenFields: eForumNew.querySelectorAll('input[type=hidden]'), |
| 961 | ondiscard: ()=>{ |
| 962 | window.location = F.repoUrl('forum'); |
| 963 | }, |
| 964 | onsubmit: (fpe, response)=>{ |
| 965 | window.location = F.repoUrl('forumpost/'+response.uuid); |
| 966 | } |
| 967 | }); |
| 968 | eForumNew.parentElement.insertBefore(fpe.widget, eForumNew); |
| 969 | eForumNew.remove(); |
| 970 | fossil.page.fpe = fpe /* for testing via the console */; |
| @@ -1083,11 +1071,11 @@ | |
| 1071 | hiddenFields: form.querySelectorAll('input[type=hidden]'), |
| 1072 | ondiscard: ondone, |
| 1073 | onsubmit: ondone, |
| 1074 | draftKey: 'draft-forumedit-'+(fEditHead || fpid).substr(0,12), |
| 1075 | edit: artifact, |
| 1076 | status: eStatusSelect?.value, |
| 1077 | inReplyTo: firt |
| 1078 | }); |
| 1079 | initFPEWidget(ePost, fpe); |
| 1080 | }); |
| 1081 | }/*editClicked()*/; |
| @@ -1094,19 +1082,24 @@ | |
| 1082 | |
| 1083 | document.body.querySelectorAll( |
| 1084 | '.forumpost-single-controls > form' |
| 1085 | ).forEach(form=>{ |
| 1086 | /* For each forum post... */ |
| 1087 | const eToDisable = [ |
| 1088 | /* List of non-editor DOM elements which need to be disabled |
| 1089 | when the editor is active. */ |
| 1090 | ]; |
| 1091 | const eThePost = form.parentElement.parentElement/*main post DOM element*/; |
| 1092 | if( !eThePost?.dataset?.fpid ){ |
| 1093 | /* The server injects these. */ |
| 1094 | console.warn("Unexpected missing fpid", eThePost); |
| 1095 | return; |
| 1096 | } |
| 1097 | /* Replace the Reply and Edit buttons with ones which will activate |
| 1098 | a ForumPostEditor. */ |
| 1099 | const btnReply = form.querySelector('input[type=submit][name=reply]'); |
| 1100 | if( btnReply ){ |
| 1101 | const b = D.button("Reply", ()=>replyClicked(form, eThePost, b, eToDisable)); |
| 1102 | b.type = 'button'/*keep container form from submitting*/; |
| 1103 | eToDisable.push(b); |
| 1104 | btnReply.parentElement.insertBefore(b, btnReply); |
| 1105 | btnReply.remove(); |
| 1106 |