mirror of
				https://github.com/go-gitea/gitea.git
				synced 2025-10-26 12:27:06 +00:00 
			
		
		
		
	
							
								
								
									
										6
									
								
								.github/workflows/pull-db-tests.yml
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										6
									
								
								.github/workflows/pull-db-tests.yml
									
									
									
									
										vendored
									
									
								
							| @@ -202,12 +202,10 @@ jobs: | ||||
|   test-mssql: | ||||
|     if: needs.files-changed.outputs.backend == 'true' || needs.files-changed.outputs.actions == 'true' | ||||
|     needs: files-changed | ||||
|     # specifying the version of ubuntu in use as mssql fails on newer kernels | ||||
|     # pending resolution from vendor | ||||
|     runs-on: ubuntu-20.04 | ||||
|     runs-on: ubuntu-latest | ||||
|     services: | ||||
|       mssql: | ||||
|         image: mcr.microsoft.com/mssql/server:2017-latest | ||||
|         image: mcr.microsoft.com/mssql/server:2019-latest | ||||
|         env: | ||||
|           ACCEPT_EULA: Y | ||||
|           MSSQL_PID: Standard | ||||
|   | ||||
| @@ -1938,7 +1938,7 @@ pulls.outdated_with_base_branch = This branch is out-of-date with the base branc | ||||
| pulls.close = Close Pull Request | ||||
| pulls.closed_at = `closed this pull request <a id="%[1]s" href="#%[1]s">%[2]s</a>` | ||||
| pulls.reopened_at = `reopened this pull request <a id="%[1]s" href="#%[1]s">%[2]s</a>` | ||||
| pulls.cmd_instruction_hint = `View <a class="show-instruction">command line instructions</a>.` | ||||
| pulls.cmd_instruction_hint = View command line instructions | ||||
| pulls.cmd_instruction_checkout_title = Checkout | ||||
| pulls.cmd_instruction_checkout_desc = From your project repository, check out a new branch and test the changes. | ||||
| pulls.cmd_instruction_merge_title = Merge | ||||
|   | ||||
| @@ -31,7 +31,9 @@ | ||||
| 						</div> | ||||
| 						<div class="item-right tw-flex tw-items-center tw-m-1"> | ||||
| 							{{if and $.CanCreateIssueDependencies (not $.Repository.IsArchived)}} | ||||
| 								<a class="delete-dependency-button ci muted" data-id="{{.Issue.ID}}" data-type="blocking" data-tooltip-content="{{ctx.Locale.Tr "repo.issues.dependency.remove_info"}}"> | ||||
| 								<a class="muted show-modal" data-modal="#issue-remove-dependency-confirm" | ||||
| 									data-modal-remove-dependency-id="{{.Issue.ID}}" data-modal-dependency-type="blocking" | ||||
| 									data-tooltip-content="{{ctx.Locale.Tr "repo.issues.dependency.remove_info"}}"> | ||||
| 									{{svg "octicon-trash" 16}} | ||||
| 								</a> | ||||
| 							{{end}} | ||||
| @@ -63,7 +65,9 @@ | ||||
| 						</div> | ||||
| 						<div class="item-right tw-flex tw-items-center tw-m-1"> | ||||
| 							{{if and $.CanCreateIssueDependencies (not $.Repository.IsArchived)}} | ||||
| 								<a class="delete-dependency-button ci muted" data-id="{{.Issue.ID}}" data-type="blockedBy" data-tooltip-content="{{ctx.Locale.Tr "repo.issues.dependency.remove_info"}}"> | ||||
| 								<a class="muted show-modal" data-modal="#issue-remove-dependency-confirm" | ||||
| 									data-modal-remove-dependency-id="{{.Issue.ID}}" data-modal-dependency-type="blockedBy" | ||||
| 									data-tooltip-content="{{ctx.Locale.Tr "repo.issues.dependency.remove_info"}}"> | ||||
| 									{{svg "octicon-trash" 16}} | ||||
| 								</a> | ||||
| 							{{end}} | ||||
| @@ -86,7 +90,9 @@ | ||||
| 							</div> | ||||
| 							<div class="item-right tw-flex tw-items-center tw-m-1"> | ||||
| 								{{if and $.CanCreateIssueDependencies (not $.Repository.IsArchived)}} | ||||
| 									<a class="delete-dependency-button ci muted" data-id="{{.Issue.ID}}" data-type="blocking" data-tooltip-content="{{ctx.Locale.Tr "repo.issues.dependency.remove_info"}}"> | ||||
| 									<a class="muted show-modal" data-modal="#issue-remove-dependency-confirm" | ||||
| 										data-modal-remove-dependency-id="{{.Issue.ID}}" data-modal-dependency-type="blocking" | ||||
| 										data-tooltip-content="{{ctx.Locale.Tr "repo.issues.dependency.remove_info"}}"> | ||||
| 										{{svg "octicon-trash" 16}} | ||||
| 									</a> | ||||
| 								{{end}} | ||||
| @@ -106,7 +112,7 @@ | ||||
| 				<form method="post" action="{{.Issue.Link}}/dependency/add" id="addDependencyForm"> | ||||
| 					{{$.CsrfTokenHtml}} | ||||
| 					<div class="ui fluid action input"> | ||||
| 						<div class="ui search selection dropdown" id="new-dependency-drop-list" data-issue-id="{{.Issue.ID}}"> | ||||
| 						<div class="ui search selection dropdown" id="new-dependency-drop-list" data-issue-id="{{.Issue.ID}}" data-issue-cross-repo-search="{{.AllowCrossRepositoryDependencies}}"> | ||||
| 							<input name="newDependency" type="hidden"> | ||||
| 							{{svg "octicon-triangle-down" 14 "dropdown icon"}} | ||||
| 							<input type="text" class="search"> | ||||
| @@ -122,28 +128,19 @@ | ||||
| 	</div> | ||||
|  | ||||
| 	{{if and .CanCreateIssueDependencies (not .Repository.IsArchived)}} | ||||
| 		<input type="hidden" id="crossRepoSearch" value="{{.AllowCrossRepositoryDependencies}}"> | ||||
|  | ||||
| 		<div class="ui g-modal-confirm modal remove-dependency"> | ||||
| 			<div class="header"> | ||||
| 				{{svg "octicon-trash"}} | ||||
| 				{{ctx.Locale.Tr "repo.issues.dependency.remove_header"}} | ||||
| 			</div> | ||||
| 		<form id="issue-remove-dependency-confirm" class="ui g-modal-confirm modal" method="post" action="{{.Issue.Link}}/dependency/delete"> | ||||
| 			<div class="header">{{svg "octicon-trash"}} {{ctx.Locale.Tr "repo.issues.dependency.remove_header"}}</div> | ||||
| 			<div class="content"> | ||||
| 				<form method="post" action="{{.Issue.Link}}/dependency/delete" id="removeDependencyForm"> | ||||
| 				{{$.CsrfTokenHtml}} | ||||
| 					<input type="hidden" value="" name="removeDependencyID" id="removeDependencyID"> | ||||
| 					<input type="hidden" value="" name="dependencyType" id="dependencyType"> | ||||
| 				</form> | ||||
| 				<p>{{if .Issue.IsPull}} | ||||
| 					{{ctx.Locale.Tr "repo.issues.dependency.pr_remove_text"}} | ||||
| 				{{else}} | ||||
| 					{{ctx.Locale.Tr "repo.issues.dependency.issue_remove_text"}} | ||||
| 				{{end}}</p> | ||||
| 			</div> | ||||
| 				<input type="hidden" value="" name="removeDependencyID" class="remove-dependency-id"> | ||||
| 				<input type="hidden" value="" name="dependencyType" class="dependency-type"> | ||||
| 				<p> | ||||
| 					{{ctx.Locale.Tr (Iif .Issue.IsPull "repo.issues.dependency.pr_remove_text" "repo.issues.dependency.issue_remove_text")}} | ||||
| 				</p> | ||||
| 				{{$ModalButtonCancelText := ctx.Locale.Tr "repo.issues.dependency.cancel"}} | ||||
| 				{{$ModalButtonOkText := ctx.Locale.Tr "repo.issues.dependency.remove"}} | ||||
| 				{{template "base/modal_actions_confirm" (dict "." . "ModalButtonCancelText" $ModalButtonCancelText "ModalButtonOkText" $ModalButtonOkText)}} | ||||
| 			</div> | ||||
| 		</form> | ||||
| 	{{end}} | ||||
| {{end}} | ||||
|   | ||||
| @@ -1,7 +1,5 @@ | ||||
| {{if and (or .HasIssuesOrPullsWritePermission .IsIssuePoster) (not .HasMerged) (not .Issue.IsClosed) (not .IsPullWorkInProgress)}} | ||||
| 	<div class="toggle-wip tw-mt-2" data-title="{{.Issue.Title}}" data-wip-prefix="{{index .PullRequestWorkInProgressPrefixes 0}}" data-update-url="{{.Issue.Link}}/title"> | ||||
| 		<a class="muted"> | ||||
| 	<a class="toggle-wip tw-block tw-mt-2" data-title="{{.Issue.Title}}" data-wip-prefix="{{index .PullRequestWorkInProgressPrefixes 0}}" data-update-url="{{.Issue.Link}}/title"> | ||||
| 		{{ctx.Locale.Tr "repo.pulls.still_in_progress"}} {{ctx.Locale.Tr "repo.pulls.add_prefix" (index .PullRequestWorkInProgressPrefixes 0)}} | ||||
| 	</a> | ||||
| 	</div> | ||||
| {{end}} | ||||
|   | ||||
| @@ -83,13 +83,13 @@ | ||||
| 					{{ctx.Locale.Tr "repo.pulls.data_broken"}} | ||||
| 				</div> | ||||
| 			{{else if .IsPullWorkInProgress}} | ||||
| 				<div class="item toggle-wip" data-title="{{.Issue.Title}}" data-wip-prefix="{{.WorkInProgressPrefix}}" data-update-url="{{.Issue.Link}}/title"> | ||||
| 				<div class="item"> | ||||
| 					<div class="item-section-left flex-text-inline tw-flex-1"> | ||||
| 						{{svg "octicon-x"}} | ||||
| 						{{ctx.Locale.Tr "repo.pulls.cannot_merge_work_in_progress"}} | ||||
| 					</div> | ||||
| 					{{if or .HasIssuesOrPullsWritePermission .IsIssuePoster}} | ||||
| 						<button class="ui compact button"> | ||||
| 						<button class="ui compact button toggle-wip" data-title="{{.Issue.Title}}" data-wip-prefix="{{.WorkInProgressPrefix}}" data-update-url="{{.Issue.Link}}/title"> | ||||
| 							{{ctx.Locale.Tr "repo.pulls.remove_prefix" .WorkInProgressPrefix}} | ||||
| 						</button> | ||||
| 					{{end}} | ||||
|   | ||||
| @@ -1,6 +1,7 @@ | ||||
| <div class="divider"></div> | ||||
| <div class="instruct-toggle"> {{ctx.Locale.Tr "repo.pulls.cmd_instruction_hint"}} </div> | ||||
| <div class="instruct-content tw-mt-2 tw-hidden"> | ||||
| <details> | ||||
| 	<summary>{{ctx.Locale.Tr "repo.pulls.cmd_instruction_hint"}}</summary> | ||||
| 	<div class="tw-mt-2"> | ||||
| 		<div><h3>{{ctx.Locale.Tr "repo.pulls.cmd_instruction_checkout_title"}}</h3>{{ctx.Locale.Tr "repo.pulls.cmd_instruction_checkout_desc"}}</div> | ||||
| 		{{$localBranch := .PullRequest.HeadBranch}} | ||||
| 		{{if ne .PullRequest.HeadRepo.ID .PullRequest.BaseRepo.ID}} | ||||
| @@ -53,3 +54,4 @@ | ||||
| 		</div> | ||||
| 		{{end}} | ||||
| 	</div> | ||||
| </details> | ||||
|   | ||||
| @@ -8,7 +8,7 @@ | ||||
| 		<div class="item-section-right"> | ||||
| 			{{if and $.UpdateAllowed $.UpdateByRebaseAllowed}} | ||||
| 				<div class="tw-inline-block"> | ||||
| 					<div class="ui buttons update-button"> | ||||
| 					<div id="update-pr-branch-with-base" class="ui buttons"> | ||||
| 						<button class="ui button" data-do="{{$.Link}}/update" data-redirect="{{$.Link}}"> | ||||
| 							<span class="button-text"> | ||||
| 								{{ctx.Locale.Tr "repo.pulls.update_branch"}} | ||||
|   | ||||
| @@ -1,4 +1,3 @@ | ||||
| import $ from 'jquery'; | ||||
| import {htmlEscape} from 'escape-goat'; | ||||
| import {createTippy, showTemporaryTooltip} from '../modules/tippy.ts'; | ||||
| import { | ||||
| @@ -21,35 +20,37 @@ import {ignoreAreYouSure} from '../vendor/jquery.are-you-sure.ts'; | ||||
|  | ||||
| const {appSubUrl} = window.config; | ||||
|  | ||||
| export function initRepoIssueSidebarList() { | ||||
| export function initRepoIssueSidebarDependency() { | ||||
|   const elDropdown = document.querySelector('#new-dependency-drop-list'); | ||||
|   if (!elDropdown) return; | ||||
|  | ||||
|   const issuePageInfo = parseIssuePageInfo(); | ||||
|   const crossRepoSearch = $('#crossRepoSearch').val(); | ||||
|   const crossRepoSearch = elDropdown.getAttribute('data-issue-cross-repo-search'); | ||||
|   let issueSearchUrl = `${issuePageInfo.repoLink}/issues/search?q={query}&type=${issuePageInfo.issueDependencySearchType}`; | ||||
|   if (crossRepoSearch === 'true') { | ||||
|     issueSearchUrl = `${appSubUrl}/issues/search?q={query}&priority_repo_id=${issuePageInfo.repoId}&type=${issuePageInfo.issueDependencySearchType}`; | ||||
|   } | ||||
|   fomanticQuery('#new-dependency-drop-list').dropdown({ | ||||
|   fomanticQuery(elDropdown).dropdown({ | ||||
|     fullTextSearch: true, | ||||
|     apiSettings: { | ||||
|       cache: false, | ||||
|       rawResponse: true, | ||||
|       url: issueSearchUrl, | ||||
|       onResponse(response: any) { | ||||
|         const filteredResponse = {success: true, results: [] as Array<Record<string, any>>}; | ||||
|         const currIssueId = $('#new-dependency-drop-list').data('issue-id'); | ||||
|         const currIssueId = elDropdown.getAttribute('data-issue-id'); | ||||
|         // Parse the response from the api to work with our dropdown | ||||
|         $.each(response, (_i, issue) => { | ||||
|         for (const issue of response) { | ||||
|           // Don't list current issue in the dependency list. | ||||
|           if (issue.id === currIssueId) { | ||||
|             return; | ||||
|           } | ||||
|           if (String(issue.id) === currIssueId) continue; | ||||
|           filteredResponse.results.push({ | ||||
|             value: issue.id, | ||||
|             name: `<div class="gt-ellipsis">#${issue.number} ${htmlEscape(issue.title)}</div> | ||||
| <div class="text small tw-break-anywhere">${htmlEscape(issue.repository.full_name)}</div>`, | ||||
|             value: issue.id, | ||||
|           }); | ||||
|           }); | ||||
|         } | ||||
|         return filteredResponse; | ||||
|       }, | ||||
|       cache: false, | ||||
|     }, | ||||
|   }); | ||||
| } | ||||
| @@ -181,24 +182,6 @@ export function initRepoIssueCommentDelete() { | ||||
|   }); | ||||
| } | ||||
|  | ||||
| export function initRepoIssueDependencyDelete() { | ||||
|   // Delete Issue dependency | ||||
|   $(document).on('click', '.delete-dependency-button', (e) => { | ||||
|     const id = e.currentTarget.getAttribute('data-id'); | ||||
|     const type = e.currentTarget.getAttribute('data-type'); | ||||
|  | ||||
|     $('.remove-dependency').modal({ | ||||
|       closable: false, | ||||
|       duration: 200, | ||||
|       onApprove: () => { | ||||
|         $('#removeDependencyID').val(id); | ||||
|         $('#dependencyType').val(type); | ||||
|         $('#removeDependencyForm').trigger('submit'); | ||||
|       }, | ||||
|     }).modal('show'); | ||||
|   }); | ||||
| } | ||||
|  | ||||
| export function initRepoIssueCodeCommentCancel() { | ||||
|   // Cancel inline code comment | ||||
|   document.addEventListener('click', (e: DOMEvent<MouseEvent>) => { | ||||
| @@ -215,11 +198,12 @@ export function initRepoIssueCodeCommentCancel() { | ||||
| } | ||||
|  | ||||
| export function initRepoPullRequestUpdate() { | ||||
|   // Pull Request update button | ||||
|   const pullUpdateButton = document.querySelector<HTMLButtonElement>('.update-button > button'); | ||||
|   if (!pullUpdateButton) return; | ||||
|   const prUpdateButtonContainer = document.querySelector('#update-pr-branch-with-base'); | ||||
|   if (!prUpdateButtonContainer) return; | ||||
|  | ||||
|   pullUpdateButton.addEventListener('click', async function (e) { | ||||
|   const prUpdateButton = prUpdateButtonContainer.querySelector<HTMLButtonElement>(':scope > button'); | ||||
|   const prUpdateDropdown = prUpdateButtonContainer.querySelector(':scope > .ui.dropdown'); | ||||
|   prUpdateButton.addEventListener('click', async function (e) { | ||||
|     e.preventDefault(); | ||||
|     const redirect = this.getAttribute('data-redirect'); | ||||
|     this.classList.add('is-loading'); | ||||
| @@ -246,27 +230,21 @@ export function initRepoPullRequestUpdate() { | ||||
|     } | ||||
|   }); | ||||
|  | ||||
|   $('.update-button > .dropdown').dropdown({ | ||||
|   fomanticQuery(prUpdateDropdown).dropdown({ | ||||
|     onChange(_text: string, _value: string, $choice: any) { | ||||
|       const choiceEl = $choice[0]; | ||||
|       const url = choiceEl.getAttribute('data-do'); | ||||
|       if (url) { | ||||
|         const buttonText = pullUpdateButton.querySelector('.button-text'); | ||||
|         const buttonText = prUpdateButton.querySelector('.button-text'); | ||||
|         if (buttonText) { | ||||
|           buttonText.textContent = choiceEl.textContent; | ||||
|         } | ||||
|         pullUpdateButton.setAttribute('data-do', url); | ||||
|         prUpdateButton.setAttribute('data-do', url); | ||||
|       } | ||||
|     }, | ||||
|   }); | ||||
| } | ||||
|  | ||||
| export function initRepoPullRequestMergeInstruction() { | ||||
|   $('.show-instruction').on('click', () => { | ||||
|     toggleElem($('.instruct-content')); | ||||
|   }); | ||||
| } | ||||
|  | ||||
| export function initRepoPullRequestAllowMaintainerEdit() { | ||||
|   const wrapper = document.querySelector('#allow-edits-from-maintainers'); | ||||
|   if (!wrapper) return; | ||||
| @@ -293,54 +271,8 @@ export function initRepoPullRequestAllowMaintainerEdit() { | ||||
|   }); | ||||
| } | ||||
|  | ||||
| export function initRepoIssueReferenceRepositorySearch() { | ||||
|   $('.issue_reference_repository_search') | ||||
|     .dropdown({ | ||||
|       apiSettings: { | ||||
|         url: `${appSubUrl}/repo/search?q={query}&limit=20`, | ||||
|         onResponse(response: any) { | ||||
|           const filteredResponse = {success: true, results: [] as Array<Record<string, any>>}; | ||||
|           $.each(response.data, (_r, repo) => { | ||||
|             filteredResponse.results.push({ | ||||
|               name: htmlEscape(repo.repository.full_name), | ||||
|               value: repo.repository.full_name, | ||||
|             }); | ||||
|           }); | ||||
|           return filteredResponse; | ||||
|         }, | ||||
|         cache: false, | ||||
|       }, | ||||
|       onChange(_value: string, _text: string, $choice: any) { | ||||
|         const $form = $choice.closest('form'); | ||||
|         if (!$form.length) return; | ||||
|  | ||||
|         $form[0].setAttribute('action', `${appSubUrl}/${_text}/issues/new`); | ||||
|       }, | ||||
|       fullTextSearch: true, | ||||
|     }); | ||||
| } | ||||
|  | ||||
| export function initRepoIssueWipTitle() { | ||||
|   $('.title_wip_desc > a').on('click', (e) => { | ||||
|     e.preventDefault(); | ||||
|  | ||||
|     const $issueTitle = $('#issue_title'); | ||||
|     $issueTitle.trigger('focus'); | ||||
|     const value = ($issueTitle.val() as string).trim().toUpperCase(); | ||||
|  | ||||
|     const wipPrefixes = $('.title_wip_desc').data('wip-prefixes'); | ||||
|     for (const prefix of wipPrefixes) { | ||||
|       if (value.startsWith(prefix.toUpperCase())) { | ||||
|         return; | ||||
|       } | ||||
|     } | ||||
|  | ||||
|     $issueTitle.val(`${wipPrefixes[0]} ${$issueTitle.val()}`); | ||||
|   }); | ||||
| } | ||||
|  | ||||
| export function initRepoIssueComments() { | ||||
|   if (!$('.repository.view.issue .timeline').length) return; | ||||
|   if (!document.querySelector('.repository.view.issue .timeline')) return; | ||||
|  | ||||
|   document.addEventListener('click', (e: DOMEvent<MouseEvent>) => { | ||||
|     const urlTarget = document.querySelector(':target'); | ||||
| @@ -352,9 +284,9 @@ export function initRepoIssueComments() { | ||||
|     if (!/^(issue|pull)(comment)?-\d+$/.test(urlTargetId)) return; | ||||
|  | ||||
|     if (!e.target.closest(`#${urlTargetId}`)) { | ||||
|       const scrollPosition = $(window).scrollTop(); | ||||
|       // if the user clicks outside the comment, remove the hash from the url | ||||
|       // use empty hash and state to avoid scrolling | ||||
|       window.location.hash = ' '; | ||||
|       $(window).scrollTop(scrollPosition); | ||||
|       window.history.pushState(null, null, ' '); | ||||
|     } | ||||
|   }); | ||||
| @@ -395,31 +327,31 @@ export function initRepoPullRequestReview() { | ||||
|     } | ||||
|   } | ||||
|  | ||||
|   $(document).on('click', '.show-outdated', function (e) { | ||||
|   addDelegatedEventListener(document, 'click', '.show-outdated', (el, e) => { | ||||
|     e.preventDefault(); | ||||
|     const id = this.getAttribute('data-comment'); | ||||
|     hideElem(this); | ||||
|     const id = el.getAttribute('data-comment'); | ||||
|     hideElem(el); | ||||
|     showElem(`#code-comments-${id}`); | ||||
|     showElem(`#code-preview-${id}`); | ||||
|     showElem(`#hide-outdated-${id}`); | ||||
|   }); | ||||
|  | ||||
|   $(document).on('click', '.hide-outdated', function (e) { | ||||
|   addDelegatedEventListener(document, 'click', '.hide-outdated', (el, e) => { | ||||
|     e.preventDefault(); | ||||
|     const id = this.getAttribute('data-comment'); | ||||
|     hideElem(this); | ||||
|     const id = el.getAttribute('data-comment'); | ||||
|     hideElem(el); | ||||
|     hideElem(`#code-comments-${id}`); | ||||
|     hideElem(`#code-preview-${id}`); | ||||
|     showElem(`#show-outdated-${id}`); | ||||
|   }); | ||||
|  | ||||
|   $(document).on('click', 'button.comment-form-reply', async function (e) { | ||||
|   addDelegatedEventListener(document, 'click', 'button.comment-form-reply', (el, e) => { | ||||
|     e.preventDefault(); | ||||
|     await handleReply(this); | ||||
|     handleReply(el); | ||||
|   }); | ||||
|  | ||||
|   // The following part is only for diff views | ||||
|   if (!$('.repository.pull.diff').length) return; | ||||
|   if (!document.querySelector('.repository.pull.diff')) return; | ||||
|  | ||||
|   const elReviewBtn = document.querySelector('.js-btn-review'); | ||||
|   const elReviewPanel = document.querySelector('.review-box-panel.tippy-target'); | ||||
| @@ -474,26 +406,67 @@ export function initRepoPullRequestReview() { | ||||
| } | ||||
|  | ||||
| export function initRepoIssueReferenceIssue() { | ||||
|   const elDropdown = document.querySelector('.issue_reference_repository_search'); | ||||
|   if (!elDropdown) return; | ||||
|   const form = elDropdown.closest('form'); | ||||
|   fomanticQuery(elDropdown).dropdown({ | ||||
|     fullTextSearch: true, | ||||
|     apiSettings: { | ||||
|       cache: false, | ||||
|       rawResponse: true, | ||||
|       url: `${appSubUrl}/repo/search?q={query}&limit=20`, | ||||
|       onResponse(response: any) { | ||||
|         const filteredResponse = {success: true, results: [] as Array<Record<string, any>>}; | ||||
|         for (const repo of response.data) { | ||||
|           filteredResponse.results.push({ | ||||
|             name: htmlEscape(repo.repository.full_name), | ||||
|             value: repo.repository.full_name, | ||||
|           }); | ||||
|         } | ||||
|         return filteredResponse; | ||||
|       }, | ||||
|     }, | ||||
|     onChange(_value: string, _text: string, _$choice: any) { | ||||
|       form.setAttribute('action', `${appSubUrl}/${_text}/issues/new`); | ||||
|     }, | ||||
|   }); | ||||
|  | ||||
|   // Reference issue | ||||
|   $(document).on('click', '.reference-issue', function (e) { | ||||
|     const target = this.getAttribute('data-target'); | ||||
|     const content = document.querySelector(`#${target}`)?.textContent ?? ''; | ||||
|     const poster = this.getAttribute('data-poster-username'); | ||||
|     const reference = toAbsoluteUrl(this.getAttribute('data-reference')); | ||||
|     const modalSelector = this.getAttribute('data-modal'); | ||||
|     const modal = document.querySelector(modalSelector); | ||||
|     const textarea = modal.querySelector('textarea[name="content"]'); | ||||
|     textarea.value = `${content}\n\n_Originally posted by @${poster} in ${reference}_`; | ||||
|     $(modal).modal('show'); | ||||
|   addDelegatedEventListener(document, 'click', '.reference-issue', (el, e) => { | ||||
|     e.preventDefault(); | ||||
|     const target = el.getAttribute('data-target'); | ||||
|     const content = document.querySelector(`#${target}`)?.textContent ?? ''; | ||||
|     const poster = el.getAttribute('data-poster-username'); | ||||
|     const reference = toAbsoluteUrl(el.getAttribute('data-reference')); | ||||
|     const modalSelector = el.getAttribute('data-modal'); | ||||
|     const modal = document.querySelector(modalSelector); | ||||
|     const textarea = modal.querySelector<HTMLTextAreaElement>('textarea[name="content"]'); | ||||
|     textarea.value = `${content}\n\n_Originally posted by @${poster} in ${reference}_`; | ||||
|     fomanticQuery(modal).modal('show'); | ||||
|   }); | ||||
| } | ||||
|  | ||||
| export function initRepoIssueWipToggle() { | ||||
|   // Toggle WIP | ||||
|   $('.toggle-wip a, .toggle-wip button').on('click', async (e) => { | ||||
| export function initRepoIssueWipNewTitle() { | ||||
|   // Toggle WIP for new PR | ||||
|   queryElems(document, '.title_wip_desc > a', (el) => el.addEventListener('click', (e) => { | ||||
|     e.preventDefault(); | ||||
|     const toggleWip = e.currentTarget.closest('.toggle-wip'); | ||||
|     const wipPrefixes = JSON.parse(el.closest('.title_wip_desc').getAttribute('data-wip-prefixes')); | ||||
|     const titleInput = document.querySelector<HTMLInputElement>('#issue_title'); | ||||
|     const titleValue = titleInput.value; | ||||
|     for (const prefix of wipPrefixes) { | ||||
|       if (titleValue.startsWith(prefix.toUpperCase())) { | ||||
|         return; | ||||
|       } | ||||
|     } | ||||
|     titleInput.value = `${wipPrefixes[0]} ${titleValue}`; | ||||
|   })); | ||||
| } | ||||
|  | ||||
| export function initRepoIssueWipToggle() { | ||||
|   // Toggle WIP for existing PR | ||||
|   queryElems(document, '.toggle-wip', (el) => el.addEventListener('click', async (e) => { | ||||
|     e.preventDefault(); | ||||
|     const toggleWip = el; | ||||
|     const title = toggleWip.getAttribute('data-title'); | ||||
|     const wipPrefix = toggleWip.getAttribute('data-wip-prefix'); | ||||
|     const updateUrl = toggleWip.getAttribute('data-update-url'); | ||||
| @@ -510,7 +483,7 @@ export function initRepoIssueWipToggle() { | ||||
|     } catch (error) { | ||||
|       console.error(error); | ||||
|     } | ||||
|   }); | ||||
|   })); | ||||
| } | ||||
|  | ||||
| export function initRepoIssueTitleEdit() { | ||||
| @@ -583,11 +556,11 @@ export function initRepoIssueBranchSelect() { | ||||
|   }); | ||||
| } | ||||
|  | ||||
| async function initSingleCommentEditor($commentForm: any) { | ||||
| async function initSingleCommentEditor(commentForm: HTMLFormElement) { | ||||
|   // pages: | ||||
|   // * normal new issue/pr page: no status-button, no comment-button (there is only a normal submit button which can submit empty content) | ||||
|   // * issue/pr view page: with comment form, has status-button and comment-button | ||||
|   const editor = await initComboMarkdownEditor($commentForm[0].querySelector('.combo-markdown-editor')); | ||||
|   const editor = await initComboMarkdownEditor(commentForm.querySelector('.combo-markdown-editor')); | ||||
|   const statusButton = document.querySelector<HTMLButtonElement>('#status-button'); | ||||
|   const commentButton = document.querySelector<HTMLButtonElement>('#comment-button'); | ||||
|   const syncUiState = () => { | ||||
| @@ -605,27 +578,27 @@ async function initSingleCommentEditor($commentForm: any) { | ||||
|   syncUiState(); | ||||
| } | ||||
|  | ||||
| function initIssueTemplateCommentEditors($commentForm: any) { | ||||
| function initIssueTemplateCommentEditors(commentForm: HTMLFormElement) { | ||||
|   // pages: | ||||
|   // * new issue with issue template | ||||
|   const $comboFields = $commentForm.find('.combo-editor-dropzone'); | ||||
|   const comboFields = commentForm.querySelectorAll<HTMLElement>('.combo-editor-dropzone'); | ||||
|  | ||||
|   const initCombo = async (elCombo: HTMLElement) => { | ||||
|     const $formField = $(elCombo.querySelector('.form-field-real')); | ||||
|     const fieldTextarea = elCombo.querySelector<HTMLTextAreaElement>('.form-field-real'); | ||||
|     const dropzoneContainer = elCombo.querySelector<HTMLElement>('.form-field-dropzone'); | ||||
|     const markdownEditor = elCombo.querySelector<HTMLElement>('.combo-markdown-editor'); | ||||
|  | ||||
|     const editor = await initComboMarkdownEditor(markdownEditor); | ||||
|     editor.container.addEventListener(ComboMarkdownEditor.EventEditorContentChanged, () => $formField.val(editor.value())); | ||||
|     editor.container.addEventListener(ComboMarkdownEditor.EventEditorContentChanged, () => fieldTextarea.value = editor.value()); | ||||
|  | ||||
|     $formField.on('focus', async () => { | ||||
|     fieldTextarea.addEventListener('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')); | ||||
|       showElem(commentForm.querySelectorAll('.combo-editor-dropzone .form-field-real')); | ||||
|       hideElem(commentForm.querySelectorAll('.combo-editor-dropzone .combo-markdown-editor')); | ||||
|       hideElem(commentForm.querySelectorAll('.combo-editor-dropzone .form-field-dropzone')); | ||||
|  | ||||
|       // activate this markdown editor | ||||
|       hideElem($formField); | ||||
|       hideElem(fieldTextarea); | ||||
|       showElem(markdownEditor); | ||||
|       showElem(dropzoneContainer); | ||||
|  | ||||
| @@ -634,21 +607,21 @@ function initIssueTemplateCommentEditors($commentForm: any) { | ||||
|     }); | ||||
|   }; | ||||
|  | ||||
|   for (const el of $comboFields) { | ||||
|   for (const el of comboFields) { | ||||
|     initCombo(el); | ||||
|   } | ||||
| } | ||||
|  | ||||
| export function initRepoCommentFormAndSidebar() { | ||||
|   const $commentForm = $('.comment.form'); | ||||
|   if (!$commentForm.length) return; | ||||
|   const commentForm = document.querySelector<HTMLFormElement>('.comment.form'); | ||||
|   if (!commentForm) return; | ||||
|  | ||||
|   if ($commentForm.find('.field.combo-editor-dropzone').length) { | ||||
|   if (commentForm.querySelector('.field.combo-editor-dropzone')) { | ||||
|     // at the moment, if a form has multiple combo-markdown-editors, it must be an issue template form | ||||
|     initIssueTemplateCommentEditors($commentForm); | ||||
|   } else if ($commentForm.find('.combo-markdown-editor').length) { | ||||
|     initIssueTemplateCommentEditors(commentForm); | ||||
|   } else if (commentForm.querySelector('.combo-markdown-editor')) { | ||||
|     // it's quite unclear about the "comment form" elements, sometimes it's for issue comment, sometimes it's for file editor/uploader message | ||||
|     initSingleCommentEditor($commentForm); | ||||
|     initSingleCommentEditor(commentForm); | ||||
|   } | ||||
|  | ||||
|   initRepoIssueSidebar(); | ||||
|   | ||||
| @@ -2,8 +2,8 @@ import {registerGlobalInitFunc} from '../modules/observer.ts'; | ||||
| import { | ||||
|   initRepoCommentFormAndSidebar, | ||||
|   initRepoIssueBranchSelect, initRepoIssueCodeCommentCancel, initRepoIssueCommentDelete, | ||||
|   initRepoIssueComments, initRepoIssueDependencyDelete, initRepoIssueReferenceIssue, | ||||
|   initRepoIssueTitleEdit, initRepoIssueWipToggle, | ||||
|   initRepoIssueComments, initRepoIssueReferenceIssue, | ||||
|   initRepoIssueTitleEdit, initRepoIssueWipNewTitle, initRepoIssueWipToggle, | ||||
|   initRepoPullRequestUpdate, | ||||
| } from './repo-issue.ts'; | ||||
| import {initUnicodeEscapeButton} from './repo-unicode-escape.ts'; | ||||
| @@ -54,6 +54,7 @@ export function initRepository() { | ||||
|   initRepoCloneButtons(); | ||||
|   initCitationFileCopyContent(); | ||||
|   initRepoSettings(); | ||||
|   initRepoIssueWipNewTitle(); | ||||
|  | ||||
|   // Issues | ||||
|   if (pageContent.matches('.page-content.repository.view.issue')) { | ||||
| @@ -67,7 +68,6 @@ export function initRepository() { | ||||
|     initRepoIssueReferenceIssue(); | ||||
|  | ||||
|     initRepoIssueCommentDelete(); | ||||
|     initRepoIssueDependencyDelete(); | ||||
|     initRepoIssueCodeCommentCancel(); | ||||
|     initRepoPullRequestUpdate(); | ||||
|     initCompReactionSelector(); | ||||
|   | ||||
| @@ -20,15 +20,8 @@ import {initStopwatch} from './features/stopwatch.ts'; | ||||
| import {initFindFileInRepo} from './features/repo-findfile.ts'; | ||||
| import {initMarkupContent} from './markup/content.ts'; | ||||
| import {initPdfViewer} from './render/pdf.ts'; | ||||
|  | ||||
| import {initUserAuthOauth2, initUserCheckAppUrl} from './features/user-auth.ts'; | ||||
| import { | ||||
|   initRepoIssueReferenceRepositorySearch, | ||||
|   initRepoIssueWipTitle, | ||||
|   initRepoPullRequestMergeInstruction, | ||||
|   initRepoPullRequestAllowMaintainerEdit, | ||||
|   initRepoPullRequestReview, initRepoIssueSidebarList, initRepoIssueFilterItemLabel, | ||||
| } from './features/repo-issue.ts'; | ||||
| import {initRepoPullRequestAllowMaintainerEdit, initRepoPullRequestReview, initRepoIssueSidebarDependency, initRepoIssueFilterItemLabel} from './features/repo-issue.ts'; | ||||
| import {initRepoEllipsisButton, initCommitStatuses} from './features/repo-commit.ts'; | ||||
| import {initRepoTopicBar} from './features/repo-home.ts'; | ||||
| import {initAdminCommon} from './features/admin/common.ts'; | ||||
| @@ -137,13 +130,10 @@ onDomReady(() => { | ||||
|     initRepoIssueContentHistory, | ||||
|     initRepoIssueList, | ||||
|     initRepoIssueFilterItemLabel, | ||||
|     initRepoIssueSidebarList, | ||||
|     initRepoIssueReferenceRepositorySearch, | ||||
|     initRepoIssueWipTitle, | ||||
|     initRepoIssueSidebarDependency, | ||||
|     initRepoMigration, | ||||
|     initRepoMigrationStatusChecker, | ||||
|     initRepoProject, | ||||
|     initRepoPullRequestMergeInstruction, | ||||
|     initRepoPullRequestAllowMaintainerEdit, | ||||
|     initRepoPullRequestReview, | ||||
|     initRepoRelease, | ||||
|   | ||||
		Reference in New Issue
	
	Block a user
	 wxiaoguang
					wxiaoguang