From 1bdb4e8725a12f8fcbfb9dcf12fc5ccc88d3557d Mon Sep 17 00:00:00 2001 From: yp05327 <576951401@qq.com> Date: Fri, 28 Apr 2023 08:23:29 +0000 Subject: [PATCH 01/14] wip --- modules/issue/template/template.go | 6 ++++++ modules/structs/issue.go | 11 ++++++----- templates/repo/issue/fields/markdowneditor.tmpl | 4 ++++ templates/repo/issue/new_form.tmpl | 2 ++ 4 files changed, 18 insertions(+), 5 deletions(-) create mode 100644 templates/repo/issue/fields/markdowneditor.tmpl diff --git a/modules/issue/template/template.go b/modules/issue/template/template.go index 0f19d87e8d5dc..117aef5619b79 100644 --- a/modules/issue/template/template.go +++ b/modules/issue/template/template.go @@ -98,6 +98,12 @@ func validateYaml(template *api.IssueTemplate) error { if err := validateOptions(field, idx); err != nil { return err } + case api.IssueFormFieldTypeMarkdownEditor: + if err := validateStringItem(position, field.Attributes, false, + "description", + ); err != nil { + return err + } default: return position.Errorf("unknown type") } diff --git a/modules/structs/issue.go b/modules/structs/issue.go index 04e169df84197..26fe5044780d8 100644 --- a/modules/structs/issue.go +++ b/modules/structs/issue.go @@ -128,11 +128,12 @@ type IssueDeadline struct { type IssueFormFieldType string const ( - IssueFormFieldTypeMarkdown IssueFormFieldType = "markdown" - IssueFormFieldTypeTextarea IssueFormFieldType = "textarea" - IssueFormFieldTypeInput IssueFormFieldType = "input" - IssueFormFieldTypeDropdown IssueFormFieldType = "dropdown" - IssueFormFieldTypeCheckboxes IssueFormFieldType = "checkboxes" + IssueFormFieldTypeMarkdown IssueFormFieldType = "markdown" + IssueFormFieldTypeTextarea IssueFormFieldType = "textarea" + IssueFormFieldTypeInput IssueFormFieldType = "input" + IssueFormFieldTypeDropdown IssueFormFieldType = "dropdown" + IssueFormFieldTypeCheckboxes IssueFormFieldType = "checkboxes" + IssueFormFieldTypeMarkdownEditor IssueFormFieldType = "markdowneditor" ) // IssueFormField represents a form field diff --git a/templates/repo/issue/fields/markdowneditor.tmpl b/templates/repo/issue/fields/markdowneditor.tmpl new file mode 100644 index 0000000000000..85b1f00a4c178 --- /dev/null +++ b/templates/repo/issue/fields/markdowneditor.tmpl @@ -0,0 +1,4 @@ +<div class="field"> + {{template "repo/issue/fields/header" .}} + {{template "repo/issue/comment_tab" $}} +</div> diff --git a/templates/repo/issue/new_form.tmpl b/templates/repo/issue/new_form.tmpl index d00a4813d250f..f603fd92a47e1 100644 --- a/templates/repo/issue/new_form.tmpl +++ b/templates/repo/issue/new_form.tmpl @@ -29,6 +29,8 @@ {{template "repo/issue/fields/dropdown" dict "Context" $.Context "item" .}} {{else if eq .Type "checkboxes"}} {{template "repo/issue/fields/checkboxes" dict "Context" $.Context "item" .}} + {{else if eq .Type "markdowneditor"}} + {{template "repo/issue/fields/markdowneditor" dict "Context" $.Context "item" $}} {{end}} {{end}} {{if .IsAttachmentEnabled}} From df498c7334babd8f890fbe02d84810a72b203e8c Mon Sep 17 00:00:00 2001 From: yp05327 <576951401@qq.com> Date: Mon, 1 May 2023 02:49:25 +0000 Subject: [PATCH 02/14] fix tmpl --- templates/repo/issue/fields/markdowneditor.tmpl | 2 +- templates/repo/issue/new_form.tmpl | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/templates/repo/issue/fields/markdowneditor.tmpl b/templates/repo/issue/fields/markdowneditor.tmpl index 85b1f00a4c178..3c8bea1327ed7 100644 --- a/templates/repo/issue/fields/markdowneditor.tmpl +++ b/templates/repo/issue/fields/markdowneditor.tmpl @@ -1,4 +1,4 @@ <div class="field"> {{template "repo/issue/fields/header" .}} - {{template "repo/issue/comment_tab" $}} + {{template "repo/issue/comment_tab" .Context.Data}} </div> diff --git a/templates/repo/issue/new_form.tmpl b/templates/repo/issue/new_form.tmpl index f603fd92a47e1..4e1980902723b 100644 --- a/templates/repo/issue/new_form.tmpl +++ b/templates/repo/issue/new_form.tmpl @@ -30,7 +30,7 @@ {{else if eq .Type "checkboxes"}} {{template "repo/issue/fields/checkboxes" dict "Context" $.Context "item" .}} {{else if eq .Type "markdowneditor"}} - {{template "repo/issue/fields/markdowneditor" dict "Context" $.Context "item" $}} + {{template "repo/issue/fields/markdowneditor" dict "Context" $.Context "item" .}} {{end}} {{end}} {{if .IsAttachmentEnabled}} From 759c9f7bd0d754b4793c6349a5c1464bdca361a9 Mon Sep 17 00:00:00 2001 From: yp05327 <576951401@qq.com> Date: Mon, 1 May 2023 03:01:05 +0000 Subject: [PATCH 03/14] remove upload --- templates/repo/issue/new_form.tmpl | 5 ----- 1 file changed, 5 deletions(-) diff --git a/templates/repo/issue/new_form.tmpl b/templates/repo/issue/new_form.tmpl index 4e1980902723b..187285258ea17 100644 --- a/templates/repo/issue/new_form.tmpl +++ b/templates/repo/issue/new_form.tmpl @@ -33,11 +33,6 @@ {{template "repo/issue/fields/markdowneditor" dict "Context" $.Context "item" .}} {{end}} {{end}} - {{if .IsAttachmentEnabled}} - <div class="field"> - {{template "repo/upload" .}} - </div> - {{end}} {{else}} {{template "repo/issue/comment_tab" .}} {{end}} From ce9ce245fcbd2e87c901465d7b640b2a23a395a0 Mon Sep 17 00:00:00 2001 From: yp05327 <576951401@qq.com> Date: Mon, 1 May 2023 06:44:05 +0000 Subject: [PATCH 04/14] reuse textarea --- modules/issue/template/template.go | 6 --- modules/structs/issue.go | 11 ++--- .../repo/issue/fields/markdowneditor.tmpl | 4 -- templates/repo/issue/fields/textarea.tmpl | 21 +++++++-- templates/repo/issue/new_form.tmpl | 2 - .../js/features/comp/ComboMarkdownEditor.js | 20 ++++---- web_src/js/features/repo-issue.js | 46 +++++++++++++++++-- web_src/js/features/repo-legacy.js | 3 +- web_src/js/features/repo-wiki.js | 2 +- web_src/js/index.js | 2 + 10 files changed, 80 insertions(+), 37 deletions(-) delete mode 100644 templates/repo/issue/fields/markdowneditor.tmpl diff --git a/modules/issue/template/template.go b/modules/issue/template/template.go index 117aef5619b79..0f19d87e8d5dc 100644 --- a/modules/issue/template/template.go +++ b/modules/issue/template/template.go @@ -98,12 +98,6 @@ func validateYaml(template *api.IssueTemplate) error { if err := validateOptions(field, idx); err != nil { return err } - case api.IssueFormFieldTypeMarkdownEditor: - if err := validateStringItem(position, field.Attributes, false, - "description", - ); err != nil { - return err - } default: return position.Errorf("unknown type") } diff --git a/modules/structs/issue.go b/modules/structs/issue.go index 26fe5044780d8..04e169df84197 100644 --- a/modules/structs/issue.go +++ b/modules/structs/issue.go @@ -128,12 +128,11 @@ type IssueDeadline struct { type IssueFormFieldType string const ( - IssueFormFieldTypeMarkdown IssueFormFieldType = "markdown" - IssueFormFieldTypeTextarea IssueFormFieldType = "textarea" - IssueFormFieldTypeInput IssueFormFieldType = "input" - IssueFormFieldTypeDropdown IssueFormFieldType = "dropdown" - IssueFormFieldTypeCheckboxes IssueFormFieldType = "checkboxes" - IssueFormFieldTypeMarkdownEditor IssueFormFieldType = "markdowneditor" + IssueFormFieldTypeMarkdown IssueFormFieldType = "markdown" + IssueFormFieldTypeTextarea IssueFormFieldType = "textarea" + IssueFormFieldTypeInput IssueFormFieldType = "input" + IssueFormFieldTypeDropdown IssueFormFieldType = "dropdown" + IssueFormFieldTypeCheckboxes IssueFormFieldType = "checkboxes" ) // IssueFormField represents a form field diff --git a/templates/repo/issue/fields/markdowneditor.tmpl b/templates/repo/issue/fields/markdowneditor.tmpl deleted file mode 100644 index 3c8bea1327ed7..0000000000000 --- a/templates/repo/issue/fields/markdowneditor.tmpl +++ /dev/null @@ -1,4 +0,0 @@ -<div class="field"> - {{template "repo/issue/fields/header" .}} - {{template "repo/issue/comment_tab" .Context.Data}} -</div> diff --git a/templates/repo/issue/fields/textarea.tmpl b/templates/repo/issue/fields/textarea.tmpl index ad3c5efa045c4..99d0fead84eb7 100644 --- a/templates/repo/issue/fields/textarea.tmpl +++ b/templates/repo/issue/fields/textarea.tmpl @@ -1,6 +1,21 @@ -<div class="field"> +<div class="field markdown-textarea"> {{template "repo/issue/fields/header" .}} {{/* FIXME: preview markdown result */}} - {{/* FIXME: required validation for markdown editor */}} - <textarea name="form-field-{{.item.ID}}" placeholder="{{.item.Attributes.placeholder}}" {{if and .item.Validations.required .item.Attributes.render}}required{{end}}>{{.item.Attributes.value}}</textarea> + <textarea class="textarea" name="form-field-{{.item.ID}}" placeholder="{{.item.Attributes.placeholder}}" {{if and .item.Validations.required .item.Attributes.render}}required{{end}}>{{.item.Attributes.value}}</textarea> + + {{$ := .Context.Data}} + {{template "shared/combomarkdowneditor" (dict + "locale" $.locale + "MarkdownPreviewUrl" (print $.Repository.Link "/markup") + "MarkdownPreviewContext" $.RepoLink + "TextareaName" "content" + "TextareaPlaceholder" ($.locale.Tr "repo.diff.comment.placeholder") + "DropzoneParentContainer" "form, .ui.form" + )}} </div> + +{{if $.IsAttachmentEnabled}} +<div class="field markdown-textarea"> + {{template "repo/upload" $}} +</div> +{{end}} \ No newline at end of file diff --git a/templates/repo/issue/new_form.tmpl b/templates/repo/issue/new_form.tmpl index 187285258ea17..782663154a19e 100644 --- a/templates/repo/issue/new_form.tmpl +++ b/templates/repo/issue/new_form.tmpl @@ -29,8 +29,6 @@ {{template "repo/issue/fields/dropdown" dict "Context" $.Context "item" .}} {{else if eq .Type "checkboxes"}} {{template "repo/issue/fields/checkboxes" dict "Context" $.Context "item" .}} - {{else if eq .Type "markdowneditor"}} - {{template "repo/issue/fields/markdowneditor" dict "Context" $.Context "item" .}} {{end}} {{end}} {{else}} diff --git a/web_src/js/features/comp/ComboMarkdownEditor.js b/web_src/js/features/comp/ComboMarkdownEditor.js index 9995033e8978e..525bb1d679887 100644 --- a/web_src/js/features/comp/ComboMarkdownEditor.js +++ b/web_src/js/features/comp/ComboMarkdownEditor.js @@ -370,17 +370,15 @@ export function getComboMarkdownEditor(el) { return el?._giteaComboMarkdownEditor; } -export async function initComboMarkdownEditor(container, options = {}) { - if (container instanceof $) { - if (container.length !== 1) { - throw new Error('initComboMarkdownEditor: container must be a single element'); - } - container = container[0]; +export async function initComboMarkdownEditor(containers, options = {}) { + if (!containers) { + throw new Error('initComboMarkdownEditor: container list is null'); } - if (!container) { - throw new Error('initComboMarkdownEditor: container is null'); + const editors = []; + for (const container of containers) { + const editor = new ComboMarkdownEditor(container, options); + await editor.init(); + editors.push(editor); } - const editor = new ComboMarkdownEditor(container, options); - await editor.init(); - return editor; + return editors; } diff --git a/web_src/js/features/repo-issue.js b/web_src/js/features/repo-issue.js index 63fae3a37cb47..118e2fc3ee262 100644 --- a/web_src/js/features/repo-issue.js +++ b/web_src/js/features/repo-issue.js @@ -392,7 +392,8 @@ export async function handleReply($el) { const $textarea = form.find('textarea'); let editor = getComboMarkdownEditor($textarea); if (!editor) { - editor = await initComboMarkdownEditor(form.find('.combo-markdown-editor')); + const editors = await initComboMarkdownEditor(form.find('.combo-markdown-editor')); + editor = editors[0]; } editor.focus(); return editor; @@ -522,8 +523,8 @@ export function initRepoPullRequestReview() { td.find("input[name='side']").val(side === 'left' ? 'previous' : 'proposed'); td.find("input[name='path']").val(path); - const editor = await initComboMarkdownEditor(td.find('.combo-markdown-editor')); - editor.focus(); + const editors = await initComboMarkdownEditor(td.find('.combo-markdown-editor')); + editors[0].focus(); } }); } @@ -634,3 +635,42 @@ export function initRepoIssueBranchSelect() { }; $('#branch-select > .item').on('click', changeBranchSelect); } + +export function initRepoIssueMarkdownTextarea() { + const hiddenTextarea = function (target) { + const comboMarkdownEditor = $(target).parent().find('.combo-markdown-editor'); + const markdownTextEditor = comboMarkdownEditor.find('.markdown-text-editor'); + const dropzone = $(target).parent().next().find('.dropzone'); + // show combo markdown editor + comboMarkdownEditor.removeClass('gt-hidden'); + markdownTextEditor.trigger('focus'); + if (dropzone) { + dropzone.removeClass('gt-hidden'); + } + // hidden textarea + $(target).addClass('gt-hidden'); + }; + + const showTextarea = function (target) { + const comboMarkdownEditor = $(target).parent().find('.combo-markdown-editor'); + const markdownTextEditor = comboMarkdownEditor.find('.markdown-text-editor'); + const dropzone = $(target).parent().next().find('.dropzone'); + // hidden combo markdown editor + $(comboMarkdownEditor).addClass('gt-hidden'); + if (dropzone) { + $(dropzone).addClass('gt-hidden'); + } + // show textarea + $(target).removeClass('gt-hidden'); + // sync textarea content + $(target).val($(markdownTextEditor).val()); + }; + + // default display textarea + $('.markdown-textarea .textarea').each((_, target) => showTextarea(target)); + + $('.markdown-textarea .textarea').on('click', function() { + hiddenTextarea(this); + $('.markdown-textarea .textarea').not(this).each((_, target) => showTextarea(target)); + }); +} diff --git a/web_src/js/features/repo-legacy.js b/web_src/js/features/repo-legacy.js index 851a9b855e6b3..31000a3884113 100644 --- a/web_src/js/features/repo-legacy.js +++ b/web_src/js/features/repo-legacy.js @@ -439,7 +439,8 @@ async function onEditContent(event) { if (!$editContentZone.html()) { $editContentZone.html($('#issue-comment-editor-template').html()); - comboMarkdownEditor = await initComboMarkdownEditor($editContentZone.find('.combo-markdown-editor')); + const comboMarkdownEditors = await initComboMarkdownEditor($editContentZone.find('.combo-markdown-editor')); + comboMarkdownEditor = comboMarkdownEditors[0]; const $dropzone = $editContentZone.find('.dropzone'); const dz = await setupDropzone($dropzone); diff --git a/web_src/js/features/repo-wiki.js b/web_src/js/features/repo-wiki.js index 09202a303ce86..bf5fe40902876 100644 --- a/web_src/js/features/repo-wiki.js +++ b/web_src/js/features/repo-wiki.js @@ -61,7 +61,7 @@ async function initRepoWikiFormEditor() { 'clean-block', 'preview', 'fullscreen', 'side-by-side', '|', 'gitea-switch-to-textarea' ], }, - }); + })[0]; $form.on('submit', () => { if (!validateTextareaNonEmpty($editArea)) { diff --git a/web_src/js/index.js b/web_src/js/index.js index f7cbb24e8562e..7d4b5f2e34b23 100644 --- a/web_src/js/index.js +++ b/web_src/js/index.js @@ -25,6 +25,7 @@ import {initCommentContent, initMarkupContent} from './markup/content.js'; import {initUserAuthLinkAccountView, initUserAuthOauth2} from './features/user-auth.js'; import { initRepoIssueDue, + initRepoIssueMarkdownTextarea, initRepoIssueReferenceRepositorySearch, initRepoIssueTimeTracking, initRepoIssueWipTitle, @@ -146,6 +147,7 @@ onDomReady(() => { initRepoIssueDue(); initRepoIssueList(); initRepoIssueSidebarList(); + initRepoIssueMarkdownTextarea(); initRepoIssueReferenceRepositorySearch(); initRepoIssueTimeTracking(); initRepoIssueWipTitle(); From ff6146a9a99a33175f6b62088f5a23d5fd6b8457 Mon Sep 17 00:00:00 2001 From: yp05327 <576951401@qq.com> Date: Mon, 1 May 2023 06:58:36 +0000 Subject: [PATCH 05/14] convert to listen focus event --- web_src/js/features/repo-issue.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/web_src/js/features/repo-issue.js b/web_src/js/features/repo-issue.js index 118e2fc3ee262..55f30c27c5e1a 100644 --- a/web_src/js/features/repo-issue.js +++ b/web_src/js/features/repo-issue.js @@ -669,7 +669,7 @@ export function initRepoIssueMarkdownTextarea() { // default display textarea $('.markdown-textarea .textarea').each((_, target) => showTextarea(target)); - $('.markdown-textarea .textarea').on('click', function() { + $('.markdown-textarea .textarea').on('focus', function() { hiddenTextarea(this); $('.markdown-textarea .textarea').not(this).each((_, target) => showTextarea(target)); }); From 2db0fb4637783455756f39c959fe605eee30a0bf Mon Sep 17 00:00:00 2001 From: yp05327 <576951401@qq.com> Date: Mon, 1 May 2023 07:10:51 +0000 Subject: [PATCH 06/14] add default value --- templates/repo/issue/fields/textarea.tmpl | 1 + 1 file changed, 1 insertion(+) diff --git a/templates/repo/issue/fields/textarea.tmpl b/templates/repo/issue/fields/textarea.tmpl index 99d0fead84eb7..8b7d2f05b94f2 100644 --- a/templates/repo/issue/fields/textarea.tmpl +++ b/templates/repo/issue/fields/textarea.tmpl @@ -9,6 +9,7 @@ "MarkdownPreviewUrl" (print $.Repository.Link "/markup") "MarkdownPreviewContext" $.RepoLink "TextareaName" "content" + "TextareaContent" .item.Attributes.value "TextareaPlaceholder" ($.locale.Tr "repo.diff.comment.placeholder") "DropzoneParentContainer" "form, .ui.form" )}} From f39e26f87b405c2efa0aede9267198a425705bf3 Mon Sep 17 00:00:00 2001 From: yp05327 <576951401@qq.com> Date: Mon, 1 May 2023 07:12:36 +0000 Subject: [PATCH 07/14] fix lint --- templates/repo/issue/fields/textarea.tmpl | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/templates/repo/issue/fields/textarea.tmpl b/templates/repo/issue/fields/textarea.tmpl index 8b7d2f05b94f2..b42bd087115f5 100644 --- a/templates/repo/issue/fields/textarea.tmpl +++ b/templates/repo/issue/fields/textarea.tmpl @@ -2,7 +2,7 @@ {{template "repo/issue/fields/header" .}} {{/* FIXME: preview markdown result */}} <textarea class="textarea" name="form-field-{{.item.ID}}" placeholder="{{.item.Attributes.placeholder}}" {{if and .item.Validations.required .item.Attributes.render}}required{{end}}>{{.item.Attributes.value}}</textarea> - + {{$ := .Context.Data}} {{template "shared/combomarkdowneditor" (dict "locale" $.locale @@ -19,4 +19,4 @@ <div class="field markdown-textarea"> {{template "repo/upload" $}} </div> -{{end}} \ No newline at end of file +{{end}} From 3bb05571a0b62db1bc1360660b61e6d89607f089 Mon Sep 17 00:00:00 2001 From: yp05327 <576951401@qq.com> Date: Mon, 1 May 2023 07:16:58 +0000 Subject: [PATCH 08/14] fix placeholder --- templates/repo/issue/fields/textarea.tmpl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/templates/repo/issue/fields/textarea.tmpl b/templates/repo/issue/fields/textarea.tmpl index b42bd087115f5..6131f25c485b6 100644 --- a/templates/repo/issue/fields/textarea.tmpl +++ b/templates/repo/issue/fields/textarea.tmpl @@ -10,7 +10,7 @@ "MarkdownPreviewContext" $.RepoLink "TextareaName" "content" "TextareaContent" .item.Attributes.value - "TextareaPlaceholder" ($.locale.Tr "repo.diff.comment.placeholder") + "TextareaPlaceholder" .item.Attributes.placeholder "DropzoneParentContainer" "form, .ui.form" )}} </div> From ff83b3b1cdbe56f68fece8a786a22a27f761dabb Mon Sep 17 00:00:00 2001 From: yp05327 <576951401@qq.com> Date: Mon, 1 May 2023 08:08:48 +0000 Subject: [PATCH 09/14] improve --- templates/repo/issue/fields/textarea.tmpl | 7 +++---- templates/repo/issue/new_form.tmpl | 2 +- 2 files changed, 4 insertions(+), 5 deletions(-) diff --git a/templates/repo/issue/fields/textarea.tmpl b/templates/repo/issue/fields/textarea.tmpl index 6131f25c485b6..7a7f1075962c7 100644 --- a/templates/repo/issue/fields/textarea.tmpl +++ b/templates/repo/issue/fields/textarea.tmpl @@ -3,11 +3,10 @@ {{/* FIXME: preview markdown result */}} <textarea class="textarea" name="form-field-{{.item.ID}}" placeholder="{{.item.Attributes.placeholder}}" {{if and .item.Validations.required .item.Attributes.render}}required{{end}}>{{.item.Attributes.value}}</textarea> - {{$ := .Context.Data}} {{template "shared/combomarkdowneditor" (dict - "locale" $.locale - "MarkdownPreviewUrl" (print $.Repository.Link "/markup") - "MarkdownPreviewContext" $.RepoLink + "locale" .Locale + "MarkdownPreviewUrl" (print .RepoLink "/markup") + "MarkdownPreviewContext" .RepoLink "TextareaName" "content" "TextareaContent" .item.Attributes.value "TextareaPlaceholder" .item.Attributes.placeholder diff --git a/templates/repo/issue/new_form.tmpl b/templates/repo/issue/new_form.tmpl index 782663154a19e..a2abd2f001398 100644 --- a/templates/repo/issue/new_form.tmpl +++ b/templates/repo/issue/new_form.tmpl @@ -24,7 +24,7 @@ {{else if eq .Type "markdown"}} {{template "repo/issue/fields/markdown" dict "Context" $.Context "item" .}} {{else if eq .Type "textarea"}} - {{template "repo/issue/fields/textarea" dict "Context" $.Context "item" .}} + {{template "repo/issue/fields/textarea" dict "Context" $.Context "item" . "RepoLink" $.RepoLink "Locale" $.locale}} {{else if eq .Type "dropdown"}} {{template "repo/issue/fields/dropdown" dict "Context" $.Context "item" .}} {{else if eq .Type "checkboxes"}} From f26e1c9b776c54757c5ef6cdc623d0795739cbd1 Mon Sep 17 00:00:00 2001 From: yp05327 <576951401@qq.com> Date: Tue, 2 May 2023 04:48:25 +0000 Subject: [PATCH 10/14] improve --- templates/repo/issue/comment_tab.tmpl | 8 ++++---- templates/repo/issue/fields/textarea.tmpl | 10 +++++----- templates/repo/issue/new_form.tmpl | 2 +- .../js/features/comp/ComboMarkdownEditor.js | 20 ++++++++++--------- web_src/js/features/repo-issue.js | 8 ++++---- web_src/js/features/repo-legacy.js | 19 ++++++++++++------ web_src/js/features/repo-wiki.js | 2 +- 7 files changed, 39 insertions(+), 30 deletions(-) diff --git a/templates/repo/issue/comment_tab.tmpl b/templates/repo/issue/comment_tab.tmpl index c40e6ddf32e87..bcb1786692b54 100644 --- a/templates/repo/issue/comment_tab.tmpl +++ b/templates/repo/issue/comment_tab.tmpl @@ -3,7 +3,7 @@ {{if not $textareaContent}}{{$textareaContent = .PullRequestTemplate}}{{end}} {{if not $textareaContent}}{{$textareaContent = .content}}{{end}} -<div class="field"> +<div class="field markdown"> {{template "shared/combomarkdowneditor" (dict "locale" $.locale "MarkdownPreviewUrl" (print .Repository.Link "/markup") @@ -16,7 +16,7 @@ </div> {{if .IsAttachmentEnabled}} - <div class="field"> - {{template "repo/upload" .}} - </div> +<div class="field"> + {{template "repo/upload" .}} +</div> {{end}} diff --git a/templates/repo/issue/fields/textarea.tmpl b/templates/repo/issue/fields/textarea.tmpl index 7a7f1075962c7..6127a32d46de6 100644 --- a/templates/repo/issue/fields/textarea.tmpl +++ b/templates/repo/issue/fields/textarea.tmpl @@ -1,7 +1,7 @@ -<div class="field markdown-textarea"> +<div class="field textarea"> {{template "repo/issue/fields/header" .}} {{/* FIXME: preview markdown result */}} - <textarea class="textarea" name="form-field-{{.item.ID}}" placeholder="{{.item.Attributes.placeholder}}" {{if and .item.Validations.required .item.Attributes.render}}required{{end}}>{{.item.Attributes.value}}</textarea> + <textarea class="fake" name="form-field-{{.item.ID}}" placeholder="{{.item.Attributes.placeholder}}" {{if and .item.Validations.required .item.Attributes.render}}required{{end}}>{{.item.Attributes.value}}</textarea> {{template "shared/combomarkdowneditor" (dict "locale" .Locale @@ -14,8 +14,8 @@ )}} </div> -{{if $.IsAttachmentEnabled}} -<div class="field markdown-textarea"> - {{template "repo/upload" $}} +{{if .IsAttachmentEnabled}} +<div class="field"> + {{template "repo/upload" .Context.Data}} </div> {{end}} diff --git a/templates/repo/issue/new_form.tmpl b/templates/repo/issue/new_form.tmpl index a2abd2f001398..936acc7755ca7 100644 --- a/templates/repo/issue/new_form.tmpl +++ b/templates/repo/issue/new_form.tmpl @@ -24,7 +24,7 @@ {{else if eq .Type "markdown"}} {{template "repo/issue/fields/markdown" dict "Context" $.Context "item" .}} {{else if eq .Type "textarea"}} - {{template "repo/issue/fields/textarea" dict "Context" $.Context "item" . "RepoLink" $.RepoLink "Locale" $.locale}} + {{template "repo/issue/fields/textarea" dict "Context" $.Context "item" . "RepoLink" $.RepoLink "Locale" $.locale "IsAttachmentEnabled" $.IsAttachmentEnabled}} {{else if eq .Type "dropdown"}} {{template "repo/issue/fields/dropdown" dict "Context" $.Context "item" .}} {{else if eq .Type "checkboxes"}} diff --git a/web_src/js/features/comp/ComboMarkdownEditor.js b/web_src/js/features/comp/ComboMarkdownEditor.js index 525bb1d679887..9995033e8978e 100644 --- a/web_src/js/features/comp/ComboMarkdownEditor.js +++ b/web_src/js/features/comp/ComboMarkdownEditor.js @@ -370,15 +370,17 @@ export function getComboMarkdownEditor(el) { return el?._giteaComboMarkdownEditor; } -export async function initComboMarkdownEditor(containers, options = {}) { - if (!containers) { - throw new Error('initComboMarkdownEditor: container list is null'); +export async function initComboMarkdownEditor(container, options = {}) { + if (container instanceof $) { + if (container.length !== 1) { + throw new Error('initComboMarkdownEditor: container must be a single element'); + } + container = container[0]; } - const editors = []; - for (const container of containers) { - const editor = new ComboMarkdownEditor(container, options); - await editor.init(); - editors.push(editor); + if (!container) { + throw new Error('initComboMarkdownEditor: container is null'); } - return editors; + const editor = new ComboMarkdownEditor(container, options); + await editor.init(); + return editor; } diff --git a/web_src/js/features/repo-issue.js b/web_src/js/features/repo-issue.js index 55f30c27c5e1a..ec0742bca50f2 100644 --- a/web_src/js/features/repo-issue.js +++ b/web_src/js/features/repo-issue.js @@ -666,11 +666,11 @@ export function initRepoIssueMarkdownTextarea() { $(target).val($(markdownTextEditor).val()); }; - // default display textarea - $('.markdown-textarea .textarea').each((_, target) => showTextarea(target)); + // default display all textarea + $('.field.textarea .fake').each((_, target) => showTextarea(target)); - $('.markdown-textarea .textarea').on('focus', function() { + $('.field.textarea .fake').on('focus', function() { hiddenTextarea(this); - $('.markdown-textarea .textarea').not(this).each((_, target) => showTextarea(target)); + $('.field.textarea .fake').not(this).each((_, target) => showTextarea(target)); }); } diff --git a/web_src/js/features/repo-legacy.js b/web_src/js/features/repo-legacy.js index 31000a3884113..d381250b2e709 100644 --- a/web_src/js/features/repo-legacy.js +++ b/web_src/js/features/repo-legacy.js @@ -89,10 +89,18 @@ export function initRepoCommentForm() { $('#comment-form').trigger('submit'); }); - const _promise = initComboMarkdownEditor($commentForm.find('.combo-markdown-editor'), { - onContentChanged(editor) { - $statusButton.text($statusButton.attr(editor.value().trim() ? 'data-status-and-comment' : 'data-status')); - }, + // default markdown editor should have no more than one + $commentForm.find('.field.markdown .combo-markdown-editor').each((_, comboMarkdownEditor) => { + const _promise = initComboMarkdownEditor(comboMarkdownEditor, { + onContentChanged(editor) { + $statusButton.text($statusButton.attr(editor.value().trim() ? 'data-status-and-comment' : 'data-status')); + }, + }); + }); + + // issue template textarea + $commentForm.find('.field.textarea .combo-markdown-editor').each((_, comboMarkdownEditor) => { + initComboMarkdownEditor(comboMarkdownEditor); }); initBranchSelector(); @@ -439,8 +447,7 @@ async function onEditContent(event) { if (!$editContentZone.html()) { $editContentZone.html($('#issue-comment-editor-template').html()); - const comboMarkdownEditors = await initComboMarkdownEditor($editContentZone.find('.combo-markdown-editor')); - comboMarkdownEditor = comboMarkdownEditors[0]; + comboMarkdownEditor = await initComboMarkdownEditor($editContentZone.find('.combo-markdown-editor')); const $dropzone = $editContentZone.find('.dropzone'); const dz = await setupDropzone($dropzone); diff --git a/web_src/js/features/repo-wiki.js b/web_src/js/features/repo-wiki.js index bf5fe40902876..09202a303ce86 100644 --- a/web_src/js/features/repo-wiki.js +++ b/web_src/js/features/repo-wiki.js @@ -61,7 +61,7 @@ async function initRepoWikiFormEditor() { 'clean-block', 'preview', 'fullscreen', 'side-by-side', '|', 'gitea-switch-to-textarea' ], }, - })[0]; + }); $form.on('submit', () => { if (!validateTextareaNonEmpty($editArea)) { From ce5604002828f91f48a965f452ae89e5a1d60e41 Mon Sep 17 00:00:00 2001 From: wxiaoguang <wxiaoguang@gmail.com> Date: Tue, 2 May 2023 17:51:21 +0800 Subject: [PATCH 11/14] fix --- templates/repo/issue/comment_tab.tmpl | 8 +- templates/repo/issue/fields/textarea.tmpl | 38 ++++---- templates/repo/issue/new_form.tmpl | 2 +- .../js/features/comp/ComboMarkdownEditor.js | 83 ++++------------- web_src/js/features/comp/ImagePaste.js | 8 ++ web_src/js/features/comp/QuickSubmit.js | 4 +- web_src/js/features/comp/TributeExpander.js | 59 ++++++++++++ web_src/js/features/repo-issue.js | 92 +++++++++++-------- web_src/js/features/repo-legacy.js | 30 ++---- web_src/js/index.js | 2 - 10 files changed, 177 insertions(+), 149 deletions(-) create mode 100644 web_src/js/features/comp/TributeExpander.js diff --git a/templates/repo/issue/comment_tab.tmpl b/templates/repo/issue/comment_tab.tmpl index bcb1786692b54..c40e6ddf32e87 100644 --- a/templates/repo/issue/comment_tab.tmpl +++ b/templates/repo/issue/comment_tab.tmpl @@ -3,7 +3,7 @@ {{if not $textareaContent}}{{$textareaContent = .PullRequestTemplate}}{{end}} {{if not $textareaContent}}{{$textareaContent = .content}}{{end}} -<div class="field markdown"> +<div class="field"> {{template "shared/combomarkdowneditor" (dict "locale" $.locale "MarkdownPreviewUrl" (print .Repository.Link "/markup") @@ -16,7 +16,7 @@ </div> {{if .IsAttachmentEnabled}} -<div class="field"> - {{template "repo/upload" .}} -</div> + <div class="field"> + {{template "repo/upload" .}} + </div> {{end}} diff --git a/templates/repo/issue/fields/textarea.tmpl b/templates/repo/issue/fields/textarea.tmpl index 6127a32d46de6..8e9eacf17c24c 100644 --- a/templates/repo/issue/fields/textarea.tmpl +++ b/templates/repo/issue/fields/textarea.tmpl @@ -1,21 +1,25 @@ -<div class="field textarea"> +{{$useMarkdownEditor := not .item.Validations.render}} +<div class="field {{if $useMarkdownEditor}}combo-editor-dropzone{{end}}"> {{template "repo/issue/fields/header" .}} - {{/* FIXME: preview markdown result */}} - <textarea class="fake" name="form-field-{{.item.ID}}" placeholder="{{.item.Attributes.placeholder}}" {{if and .item.Validations.required .item.Attributes.render}}required{{end}}>{{.item.Attributes.value}}</textarea> - {{template "shared/combomarkdowneditor" (dict - "locale" .Locale - "MarkdownPreviewUrl" (print .RepoLink "/markup") - "MarkdownPreviewContext" .RepoLink - "TextareaName" "content" - "TextareaContent" .item.Attributes.value - "TextareaPlaceholder" .item.Attributes.placeholder - "DropzoneParentContainer" "form, .ui.form" - )}} -</div> + {{/* the real form element to provide the value */}} + <textarea class="form-field-real" name="form-field-{{.item.ID}}" placeholder="{{.item.Attributes.placeholder}}" {{if and .item.Validations.required}}required{{end}}>{{.item.Attributes.value}}</textarea> + + {{if $useMarkdownEditor}} + {{template "shared/combomarkdowneditor" (dict + "locale" .root.locale + "ContainerClasses" "gt-hidden" + "MarkdownPreviewUrl" (print .root.RepoLink "/markup") + "MarkdownPreviewContext" .root.RepoLink + "TextareaContent" .item.Attributes.value + "TextareaPlaceholder" .item.Attributes.placeholder + "DropzoneParentContainer" ".combo-editor-dropzone" + )}} -{{if .IsAttachmentEnabled}} -<div class="field"> - {{template "repo/upload" .Context.Data}} + {{if .root.IsAttachmentEnabled}} + <div class="gt-mt-4 form-field-dropzone gt-hidden"> + {{template "repo/upload" .root}} + </div> + {{end}} + {{end}} </div> -{{end}} diff --git a/templates/repo/issue/new_form.tmpl b/templates/repo/issue/new_form.tmpl index dfe795e137533..c12b8149b0864 100644 --- a/templates/repo/issue/new_form.tmpl +++ b/templates/repo/issue/new_form.tmpl @@ -24,7 +24,7 @@ {{else if eq .Type "markdown"}} {{template "repo/issue/fields/markdown" dict "Context" $.Context "item" .}} {{else if eq .Type "textarea"}} - {{template "repo/issue/fields/textarea" dict "Context" $.Context "item" . "RepoLink" $.RepoLink "Locale" $.locale "IsAttachmentEnabled" $.IsAttachmentEnabled}} + {{template "repo/issue/fields/textarea" dict "Context" $.Context "item" . "root" $}} {{else if eq .Type "dropdown"}} {{template "repo/issue/fields/dropdown" dict "Context" $.Context "item" .}} {{else if eq .Type "checkboxes"}} diff --git a/web_src/js/features/comp/ComboMarkdownEditor.js b/web_src/js/features/comp/ComboMarkdownEditor.js index 42c10e664eaa6..97b0de0216a0d 100644 --- a/web_src/js/features/comp/ComboMarkdownEditor.js +++ b/web_src/js/features/comp/ComboMarkdownEditor.js @@ -5,10 +5,9 @@ import {attachTribute} from '../tribute.js'; import {hideElem, showElem, autosize} from '../../utils/dom.js'; import {initEasyMDEImagePaste, initTextareaImagePaste} from './ImagePaste.js'; import {handleGlobalEnterQuickSubmit} from './QuickSubmit.js'; -import {emojiString} from '../emoji.js'; import {renderPreviewPanelContent} from '../repo-editor.js'; -import {matchEmoji, matchMention} from '../../utils/match.js'; import {svg} from '../../svg.js'; +import {initTributeExpander} from './TributeExpander.js'; let elementIdCounter = 0; @@ -43,14 +42,12 @@ class ComboMarkdownEditor { async init() { this.prepareEasyMDEToolbarActions(); + this.setupContainer(); this.setupTab(); this.setupDropzone(); this.setupTextarea(); - this.setupExpander(); - if (this.userPreferredEditor === 'easymde') { - await this.switchToEasyMDE(); - } + await this.switchToUserPreference(); } applyEditorHeights(el, heights) { @@ -60,6 +57,11 @@ class ComboMarkdownEditor { if (heights.maxHeight) el.style.maxHeight = heights.maxHeight; } + setupContainer() { + initTributeExpander(this.container.querySelector('text-expander')); + this.container.addEventListener('ce-editor-content-changed', (e) => this.options?.onContentChanged?.(this, e)); + } + setupTextarea() { this.textarea = this.container.querySelector('.markdown-text-editor'); this.textarea._giteaComboMarkdownEditor = this; @@ -103,64 +105,6 @@ class ComboMarkdownEditor { } } - setupExpander() { - const expander = this.container.querySelector('text-expander'); - expander?.addEventListener('text-expander-change', ({detail: {key, provide, text}}) => { - if (key === ':') { - const matches = matchEmoji(text); - if (!matches.length) return provide({matched: false}); - - const ul = document.createElement('ul'); - ul.classList.add('suggestions'); - for (const name of matches) { - const emoji = emojiString(name); - const li = document.createElement('li'); - li.setAttribute('role', 'option'); - li.setAttribute('data-value', emoji); - li.textContent = `${emoji} ${name}`; - ul.append(li); - } - - provide({matched: true, fragment: ul}); - } else if (key === '@') { - const matches = matchMention(text); - if (!matches.length) return provide({matched: false}); - - const ul = document.createElement('ul'); - ul.classList.add('suggestions'); - for (const {value, name, fullname, avatar} of matches) { - const li = document.createElement('li'); - li.setAttribute('role', 'option'); - li.setAttribute('data-value', `${key}${value}`); - - const img = document.createElement('img'); - img.src = avatar; - li.append(img); - - const nameSpan = document.createElement('span'); - nameSpan.textContent = name; - li.append(nameSpan); - - if (fullname && fullname.toLowerCase() !== name) { - const fullnameSpan = document.createElement('span'); - fullnameSpan.classList.add('fullname'); - fullnameSpan.textContent = fullname; - li.append(fullnameSpan); - } - - ul.append(li); - } - - provide({matched: true, fragment: ul}); - } - }); - expander?.addEventListener('text-expander-value', ({detail}) => { - if (detail?.item) { - detail.value = detail.item.getAttribute('data-value'); - } - }); - } - setupDropzone() { const dropzoneParentContainer = this.container.getAttribute('data-dropzone-parent-container'); if (dropzoneParentContainer) { @@ -270,7 +214,16 @@ class ComboMarkdownEditor { return processed; } + async switchToUserPreference() { + if (this.userPreferredEditor === 'easymde') { + await this.switchToEasyMDE(); + } else { + this.switchToTextarea(); + } + } + switchToTextarea() { + if (!this.easyMDE) return; showElem(this.textareaMarkdownToolbar); if (this.easyMDE) { this.easyMDE.toTextArea(); @@ -279,6 +232,8 @@ class ComboMarkdownEditor { } async switchToEasyMDE() { + if (this.easyMDE) return; + // EasyMDE's CSS should be loaded via webpack config, otherwise our own styles can not overwrite the default styles. const {default: EasyMDE} = await import(/* webpackChunkName: "easymde" */'easymde'); const easyMDEOpt = { diff --git a/web_src/js/features/comp/ImagePaste.js b/web_src/js/features/comp/ImagePaste.js index 9145b24062f26..dc335495a310f 100644 --- a/web_src/js/features/comp/ImagePaste.js +++ b/web_src/js/features/comp/ImagePaste.js @@ -25,6 +25,10 @@ function clipboardPastedImages(e) { return files; } +function triggerEditorContentChanged(target) { + target.dispatchEvent(new CustomEvent('ce-editor-content-changed', {bubbles: true})); +} + class TextareaEditor { constructor(editor) { this.editor = editor; @@ -38,6 +42,7 @@ class TextareaEditor { editor.selectionStart = startPos; editor.selectionEnd = startPos + value.length; editor.focus(); + triggerEditorContentChanged(editor); } replacePlaceholder(oldVal, newVal) { @@ -54,6 +59,7 @@ class TextareaEditor { } editor.selectionStart = editor.selectionEnd; editor.focus(); + triggerEditorContentChanged(editor); } } @@ -70,6 +76,7 @@ class CodeMirrorEditor { endPoint.ch = startPoint.ch + value.length; editor.setSelection(startPoint, endPoint); editor.focus(); + triggerEditorContentChanged(editor.getTextArea()); } replacePlaceholder(oldVal, newVal) { @@ -84,6 +91,7 @@ class CodeMirrorEditor { endPoint.ch += newVal.length; editor.setSelection(endPoint, endPoint); editor.focus(); + triggerEditorContentChanged(editor.getTextArea()); } } diff --git a/web_src/js/features/comp/QuickSubmit.js b/web_src/js/features/comp/QuickSubmit.js index 43424a949f1ec..d598a59655308 100644 --- a/web_src/js/features/comp/QuickSubmit.js +++ b/web_src/js/features/comp/QuickSubmit.js @@ -6,7 +6,9 @@ export function handleGlobalEnterQuickSubmit(target) { if ($form.length) { // here use the event to trigger the submit event (instead of calling `submit()` method directly) // otherwise the `areYouSure` handler won't be executed, then there will be an annoying "confirm to leave" dialog - $form.trigger('submit'); + if ($form[0].checkValidity()) { + $form.trigger('submit'); + } } else { // if no form, then the editor is for an AJAX request, dispatch an event to the target, let the target's event handler to do the AJAX request. // the 'ce-' prefix means this is a CustomEvent diff --git a/web_src/js/features/comp/TributeExpander.js b/web_src/js/features/comp/TributeExpander.js new file mode 100644 index 0000000000000..815c8e55457a0 --- /dev/null +++ b/web_src/js/features/comp/TributeExpander.js @@ -0,0 +1,59 @@ +import {matchEmoji, matchMention} from '../../utils/match.js'; +import {emojiString} from '../emoji.js'; + +export function initTributeExpander(expander) { + expander?.addEventListener('text-expander-change', ({detail: {key, provide, text}}) => { + if (key === ':') { + const matches = matchEmoji(text); + if (!matches.length) return provide({matched: false}); + + const ul = document.createElement('ul'); + ul.classList.add('suggestions'); + for (const name of matches) { + const emoji = emojiString(name); + const li = document.createElement('li'); + li.setAttribute('role', 'option'); + li.setAttribute('data-value', emoji); + li.textContent = `${emoji} ${name}`; + ul.append(li); + } + + provide({matched: true, fragment: ul}); + } else if (key === '@') { + const matches = matchMention(text); + if (!matches.length) return provide({matched: false}); + + const ul = document.createElement('ul'); + ul.classList.add('suggestions'); + for (const {value, name, fullname, avatar} of matches) { + const li = document.createElement('li'); + li.setAttribute('role', 'option'); + li.setAttribute('data-value', `${key}${value}`); + + const img = document.createElement('img'); + img.src = avatar; + li.append(img); + + const nameSpan = document.createElement('span'); + nameSpan.textContent = name; + li.append(nameSpan); + + if (fullname && fullname.toLowerCase() !== name) { + const fullnameSpan = document.createElement('span'); + fullnameSpan.classList.add('fullname'); + fullnameSpan.textContent = fullname; + li.append(fullnameSpan); + } + + ul.append(li); + } + + provide({matched: true, fragment: ul}); + } + }); + expander?.addEventListener('text-expander-value', ({detail}) => { + if (detail?.item) { + detail.value = detail.item.getAttribute('data-value'); + } + }); +} diff --git a/web_src/js/features/repo-issue.js b/web_src/js/features/repo-issue.js index ec0742bca50f2..1fd91b87a1193 100644 --- a/web_src/js/features/repo-issue.js +++ b/web_src/js/features/repo-issue.js @@ -392,8 +392,7 @@ export async function handleReply($el) { const $textarea = form.find('textarea'); let editor = getComboMarkdownEditor($textarea); if (!editor) { - const editors = await initComboMarkdownEditor(form.find('.combo-markdown-editor')); - editor = editors[0]; + editor = await initComboMarkdownEditor(form.find('.combo-markdown-editor')); } editor.focus(); return editor; @@ -523,8 +522,8 @@ export function initRepoPullRequestReview() { td.find("input[name='side']").val(side === 'left' ? 'previous' : 'proposed'); td.find("input[name='path']").val(path); - const editors = await initComboMarkdownEditor(td.find('.combo-markdown-editor')); - editors[0].focus(); + const editor = await initComboMarkdownEditor(td.find('.combo-markdown-editor')); + editor.focus(); } }); } @@ -636,41 +635,58 @@ export function initRepoIssueBranchSelect() { $('#branch-select > .item').on('click', changeBranchSelect); } -export function initRepoIssueMarkdownTextarea() { - const hiddenTextarea = function (target) { - const comboMarkdownEditor = $(target).parent().find('.combo-markdown-editor'); - const markdownTextEditor = comboMarkdownEditor.find('.markdown-text-editor'); - const dropzone = $(target).parent().next().find('.dropzone'); - // show combo markdown editor - comboMarkdownEditor.removeClass('gt-hidden'); - markdownTextEditor.trigger('focus'); - if (dropzone) { - dropzone.removeClass('gt-hidden'); - } - // hidden textarea - $(target).addClass('gt-hidden'); - }; +export function initSingleCommentEditor($commentForm) { + // pages: + // * normal new issue/pr page, no status-button + // * issue/pr view page, with comment form, has status-button + const opts = {}; + const $statusButton = $('#status-button'); + if ($statusButton.length) { + $statusButton.on('click', (e) => { + e.preventDefault(); + $('#status').val($statusButton.data('status-val')); + $('#comment-form').trigger('submit'); + }); + opts.onContentChanged = (editor) => { + $statusButton.text($statusButton.attr(editor.value().trim() ? 'data-status-and-comment' : 'data-status')); + }; + } + initComboMarkdownEditor($commentForm.find('.combo-markdown-editor'), opts); +} - const showTextarea = function (target) { - const comboMarkdownEditor = $(target).parent().find('.combo-markdown-editor'); - const markdownTextEditor = comboMarkdownEditor.find('.markdown-text-editor'); - const dropzone = $(target).parent().next().find('.dropzone'); - // hidden combo markdown editor - $(comboMarkdownEditor).addClass('gt-hidden'); - if (dropzone) { - $(dropzone).addClass('gt-hidden'); - } - // show textarea - $(target).removeClass('gt-hidden'); - // sync textarea content - $(target).val($(markdownTextEditor).val()); - }; +export function initIssueTemplateCommentEditors($commentForm) { + // pages: + // * new issue with issue template + const $comboFields = $commentForm.find('.combo-editor-dropzone'); - // default display all textarea - $('.field.textarea .fake').each((_, target) => showTextarea(target)); + const initCombo = async ($combo) => { + const $dropzoneContainer = $combo.find('.form-field-dropzone'); + const $formField = $combo.find('.form-field-real'); + const $markdownEditor = $combo.find('.combo-markdown-editor'); - $('.field.textarea .fake').on('focus', function() { - hiddenTextarea(this); - $('.field.textarea .fake').not(this).each((_, target) => showTextarea(target)); - }); + const editor = await initComboMarkdownEditor($markdownEditor, { + onContentChanged: (editor) => { + $formField.val(editor.value()); + } + }); + + $formField.on('focus', async () => { + // deactivate all markdown editors + showElem($commentForm.find('.combo-editor-dropzone .form-field-real')); + hideElem($commentForm.find('.combo-editor-dropzone .combo-markdown-editor')); + hideElem($commentForm.find('.combo-editor-dropzone .form-field-dropzone')); + + // activate this markdown editor + hideElem($formField); + showElem($markdownEditor); + showElem($dropzoneContainer); + + await editor.switchToUserPreference(); + editor.focus(); + }); + }; + + for (const el of $comboFields) { + initCombo($(el)); + } } diff --git a/web_src/js/features/repo-legacy.js b/web_src/js/features/repo-legacy.js index d381250b2e709..964ec16d2b008 100644 --- a/web_src/js/features/repo-legacy.js +++ b/web_src/js/features/repo-legacy.js @@ -3,7 +3,7 @@ import { initRepoIssueBranchSelect, initRepoIssueCodeCommentCancel, initRepoIssueCommentDelete, initRepoIssueComments, initRepoIssueDependencyDelete, initRepoIssueReferenceIssue, initRepoIssueTitleEdit, initRepoIssueWipToggle, - initRepoPullRequestUpdate, updateIssuesMeta, handleReply + initRepoPullRequestUpdate, updateIssuesMeta, handleReply, initIssueTemplateCommentEditors, initSingleCommentEditor, } from './repo-issue.js'; import {initUnicodeEscapeButton} from './repo-unicode-escape.js'; import {svg} from '../svg.js'; @@ -53,6 +53,13 @@ export function initRepoCommentForm() { return; } + if ($commentForm.find('.field.combo-editor-dropzone').length) { + // at the moment, if a form has multiple combo-markdown-editors, it must be a issue template form + initIssueTemplateCommentEditors($commentForm); + } else { + initSingleCommentEditor($commentForm); + } + function initBranchSelector() { const $selectBranch = $('.ui.select-branch'); const $branchMenu = $selectBranch.find('.reference-list-menu'); @@ -82,27 +89,6 @@ export function initRepoCommentForm() { }); } - const $statusButton = $('#status-button'); - $statusButton.on('click', (e) => { - e.preventDefault(); - $('#status').val($statusButton.data('status-val')); - $('#comment-form').trigger('submit'); - }); - - // default markdown editor should have no more than one - $commentForm.find('.field.markdown .combo-markdown-editor').each((_, comboMarkdownEditor) => { - const _promise = initComboMarkdownEditor(comboMarkdownEditor, { - onContentChanged(editor) { - $statusButton.text($statusButton.attr(editor.value().trim() ? 'data-status-and-comment' : 'data-status')); - }, - }); - }); - - // issue template textarea - $commentForm.find('.field.textarea .combo-markdown-editor').each((_, comboMarkdownEditor) => { - initComboMarkdownEditor(comboMarkdownEditor); - }); - initBranchSelector(); // List submits diff --git a/web_src/js/index.js b/web_src/js/index.js index 7d4b5f2e34b23..f7cbb24e8562e 100644 --- a/web_src/js/index.js +++ b/web_src/js/index.js @@ -25,7 +25,6 @@ import {initCommentContent, initMarkupContent} from './markup/content.js'; import {initUserAuthLinkAccountView, initUserAuthOauth2} from './features/user-auth.js'; import { initRepoIssueDue, - initRepoIssueMarkdownTextarea, initRepoIssueReferenceRepositorySearch, initRepoIssueTimeTracking, initRepoIssueWipTitle, @@ -147,7 +146,6 @@ onDomReady(() => { initRepoIssueDue(); initRepoIssueList(); initRepoIssueSidebarList(); - initRepoIssueMarkdownTextarea(); initRepoIssueReferenceRepositorySearch(); initRepoIssueTimeTracking(); initRepoIssueWipTitle(); From 143dcadbc228dd128c3f01692975f1931fdea535 Mon Sep 17 00:00:00 2001 From: wxiaoguang <wxiaoguang@gmail.com> Date: Wed, 3 May 2023 00:53:02 +0800 Subject: [PATCH 12/14] fix --- templates/repo/issue/fields/textarea.tmpl | 2 +- web_src/js/features/comp/ComboMarkdownEditor.js | 1 - 2 files changed, 1 insertion(+), 2 deletions(-) diff --git a/templates/repo/issue/fields/textarea.tmpl b/templates/repo/issue/fields/textarea.tmpl index 8e9eacf17c24c..49d51eb5a8ba2 100644 --- a/templates/repo/issue/fields/textarea.tmpl +++ b/templates/repo/issue/fields/textarea.tmpl @@ -1,4 +1,4 @@ -{{$useMarkdownEditor := not .item.Validations.render}} +{{$useMarkdownEditor := not .item.Attributes.render}} <div class="field {{if $useMarkdownEditor}}combo-editor-dropzone{{end}}"> {{template "repo/issue/fields/header" .}} diff --git a/web_src/js/features/comp/ComboMarkdownEditor.js b/web_src/js/features/comp/ComboMarkdownEditor.js index 97b0de0216a0d..d683988f7d76e 100644 --- a/web_src/js/features/comp/ComboMarkdownEditor.js +++ b/web_src/js/features/comp/ComboMarkdownEditor.js @@ -233,7 +233,6 @@ class ComboMarkdownEditor { async switchToEasyMDE() { if (this.easyMDE) return; - // EasyMDE's CSS should be loaded via webpack config, otherwise our own styles can not overwrite the default styles. const {default: EasyMDE} = await import(/* webpackChunkName: "easymde" */'easymde'); const easyMDEOpt = { From 49b004611e25f6be10f73d10f10a35ea74cf71cf Mon Sep 17 00:00:00 2001 From: yp05327 <576951401@qq.com> Date: Mon, 8 May 2023 05:13:18 +0000 Subject: [PATCH 13/14] fix --- web_src/js/features/repo-issue.js | 1 + 1 file changed, 1 insertion(+) diff --git a/web_src/js/features/repo-issue.js b/web_src/js/features/repo-issue.js index 3b29e30be14e4..8ecc7aa4ca2af 100644 --- a/web_src/js/features/repo-issue.js +++ b/web_src/js/features/repo-issue.js @@ -664,6 +664,7 @@ export function initRepoIssueGotoID() { hideElem($('#hashtag-button')); } }); +} export function initSingleCommentEditor($commentForm) { // pages: From d22b77f576f89dacc0d04d257c4cbff96c81e693 Mon Sep 17 00:00:00 2001 From: silverwind <me@silverwind.io> Date: Mon, 8 May 2023 23:54:05 +0200 Subject: [PATCH 14/14] rename TributeExpander to TextExpander --- web_src/js/features/comp/ComboMarkdownEditor.js | 4 ++-- .../js/features/comp/{TributeExpander.js => TextExpander.js} | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) rename web_src/js/features/comp/{TributeExpander.js => TextExpander.js} (97%) diff --git a/web_src/js/features/comp/ComboMarkdownEditor.js b/web_src/js/features/comp/ComboMarkdownEditor.js index 9e83ba6ea4fe2..103e71daae473 100644 --- a/web_src/js/features/comp/ComboMarkdownEditor.js +++ b/web_src/js/features/comp/ComboMarkdownEditor.js @@ -7,7 +7,7 @@ import {initEasyMDEImagePaste, initTextareaImagePaste} from './ImagePaste.js'; import {handleGlobalEnterQuickSubmit} from './QuickSubmit.js'; import {renderPreviewPanelContent} from '../repo-editor.js'; import {easyMDEToolbarActions} from './EasyMDEToolbarActions.js'; -import {initTributeExpander} from './TributeExpander.js'; +import {initTextExpander} from './TextExpander.js'; let elementIdCounter = 0; @@ -58,7 +58,7 @@ class ComboMarkdownEditor { } setupContainer() { - initTributeExpander(this.container.querySelector('text-expander')); + initTextExpander(this.container.querySelector('text-expander')); this.container.addEventListener('ce-editor-content-changed', (e) => this.options?.onContentChanged?.(this, e)); } diff --git a/web_src/js/features/comp/TributeExpander.js b/web_src/js/features/comp/TextExpander.js similarity index 97% rename from web_src/js/features/comp/TributeExpander.js rename to web_src/js/features/comp/TextExpander.js index 815c8e55457a0..e2840610dfd8f 100644 --- a/web_src/js/features/comp/TributeExpander.js +++ b/web_src/js/features/comp/TextExpander.js @@ -1,7 +1,7 @@ import {matchEmoji, matchMention} from '../../utils/match.js'; import {emojiString} from '../emoji.js'; -export function initTributeExpander(expander) { +export function initTextExpander(expander) { expander?.addEventListener('text-expander-change', ({detail: {key, provide, text}}) => { if (key === ':') { const matches = matchEmoji(text);