Skip to content

Commit eefc914

Browse files
KN4CK3Rsilverwind
authored andcommitted
Update content on checkbox change.
1 parent d957a15 commit eefc914

File tree

7 files changed

+64
-14
lines changed

7 files changed

+64
-14
lines changed

modules/markup/markdown/goldmark.go

Lines changed: 10 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -384,18 +384,19 @@ func (r *HTMLRenderer) renderTaskCheckBoxListItem(w util.BufWriter, source []byt
384384
} else {
385385
_, _ = w.WriteString("<li>")
386386
}
387-
end := ">"
388-
if r.XHTML {
389-
end = " />"
387+
_, _ = w.WriteString(`<input type="checkbox" disabled=""`)
388+
segments := node.FirstChild().Lines()
389+
if segments.Len() > 0 {
390+
segment := segments.At(0)
391+
_, _ = w.WriteString(fmt.Sprintf(` data-source-position="%d"`, segment.Start))
390392
}
391-
var err error
392393
if n.IsChecked {
393-
_, err = w.WriteString(`<input type="checkbox" disabled="" checked=""` + end)
394-
} else {
395-
_, err = w.WriteString(`<input type="checkbox" disabled=""` + end)
394+
_, _ = w.WriteString(` checked=""`)
396395
}
397-
if err != nil {
398-
return ast.WalkStop, err
396+
if r.XHTML {
397+
_, _ = w.WriteString(` />`)
398+
} else {
399+
_ = w.WriteByte('>')
399400
}
400401
fc := n.FirstChild()
401402
if fc != nil {

modules/markup/sanitizer.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -43,7 +43,7 @@ func ReplaceSanitizer() {
4343

4444
// Checkboxes
4545
sanitizer.policy.AllowAttrs("type").Matching(regexp.MustCompile(`^checkbox$`)).OnElements("input")
46-
sanitizer.policy.AllowAttrs("checked", "disabled").OnElements("input")
46+
sanitizer.policy.AllowAttrs("checked", "disabled", "data-source-position").OnElements("input")
4747

4848
// Custom URL-Schemes
4949
if len(setting.Markdown.CustomURLSchemes) > 0 {

templates/repo/diff/comments.tmpl

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -51,7 +51,7 @@
5151
</div>
5252
</div>
5353
<div class="ui attached segment comment-body">
54-
<div class="render-content markup">
54+
<div class="render-content markup" {{if or $.Permission.IsAdmin $.HasIssuesOrPullsWritePermission (and $.IsSigned (eq $.SignedUserID .PosterID))}}data-can-edit="true"{{end}}>
5555
{{if .RenderedContent}}
5656
{{.RenderedContent|Str2html}}
5757
{{else}}

templates/repo/issue/view_content.tmpl

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -57,7 +57,7 @@
5757
</div>
5858
</div>
5959
<div class="ui attached segment comment-body">
60-
<div class="render-content markup">
60+
<div class="render-content markup" {{if or $.Permission.IsAdmin $.HasIssuesOrPullsWritePermission $.IsIssuePoster}}data-can-edit="true"{{end}}>
6161
{{if .Issue.RenderedContent}}
6262
{{.Issue.RenderedContent|Str2html}}
6363
{{else}}

templates/repo/issue/view_content/comments.tmpl

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -64,7 +64,7 @@
6464
</div>
6565
</div>
6666
<div class="ui attached segment comment-body">
67-
<div class="render-content markup">
67+
<div class="render-content markup" {{if or $.Permission.IsAdmin $.HasIssuesOrPullsWritePermission (and $.IsSigned (eq $.SignedUserID .PosterID))}}data-can-edit="true"{{end}}>
6868
{{if .RenderedContent}}
6969
{{.RenderedContent|Str2html}}
7070
{{else}}
@@ -552,7 +552,7 @@
552552
</div>
553553
</div>
554554
<div class="text comment-content">
555-
<div class="render-content markup">
555+
<div class="render-content markup" {{if or $.Permission.IsAdmin $.HasIssuesOrPullsWritePermission (and $.IsSigned (eq $.SignedUserID .PosterID))}}data-can-edit="true"{{end}}>
556556
{{if .RenderedContent}}
557557
{{.RenderedContent|Str2html}}
558558
{{else}}

web_src/js/index.js

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@ import initServiceWorker from './features/serviceworker.js';
1919
import initTableSort from './features/tablesort.js';
2020
import {createCodeEditor, createMonaco} from './features/codeeditor.js';
2121
import {initMarkupAnchors} from './markup/anchors.js';
22+
import initMarkupTasklist from './markup/tasklist.js';
2223
import {initNotificationsTable, initNotificationCount} from './features/notification.js';
2324
import {initStopwatch} from './features/stopwatch.js';
2425
import {renderMarkupContent} from './markup/content.js';
@@ -2733,6 +2734,7 @@ $(document).ready(async () => {
27332734
searchRepositories();
27342735

27352736
initMarkupAnchors();
2737+
initMarkupTasklist();
27362738
initCommentForm();
27372739
initInstall();
27382740
initArchiveLinks();

web_src/js/markup/tasklist.js

Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,47 @@
1+
/**
2+
* Attaches `change` handlers to markdown rendered tasklist checkboxes in comments.
3+
* When a checkbox value changes, the corresponding [ ] or [x] in the markdown string is set accordingly and sent to the server.
4+
* On success it updates the raw-content on error it resets the checkbox to its original value.
5+
*/
6+
export default function initMarkupTasklist() {
7+
$(`.render-content.markup[data-can-edit='true']`).parent().each((_, container) => {
8+
const $container = $(container);
9+
const $checkboxes = $container.find(`.task-list-item input:checkbox`);
10+
11+
$checkboxes.on('change', async (ev) => {
12+
const $checkbox = $(ev.target);
13+
const checkboxCharacter = $checkbox.is(':checked') ? 'x' : ' ';
14+
const position = parseInt($checkbox.data('source-position')) + 1;
15+
16+
const $rawContent = $container.find('.raw-content');
17+
const oldContent = $rawContent.text();
18+
const newContent = oldContent.substring(0, position) + checkboxCharacter + oldContent.substring(position + 1);
19+
20+
if (newContent !== oldContent) {
21+
$checkboxes.prop('disabled', true);
22+
23+
try {
24+
const $contentZone = $container.find('.edit-content-zone');
25+
const url = $contentZone.data('update-url');
26+
const context = $contentZone.data('context');
27+
28+
await $.post(url, {
29+
_csrf: window.config.csrf,
30+
content: newContent,
31+
context,
32+
});
33+
34+
$rawContent.text(newContent);
35+
} catch (e) {
36+
$checkbox.prop('checked', !$checkbox.is(':checked'));
37+
38+
console.error(e);
39+
} finally {
40+
$checkboxes.prop('disabled', false);
41+
}
42+
}
43+
});
44+
45+
$checkboxes.prop('disabled', false);
46+
});
47+
}

0 commit comments

Comments
 (0)