import $ from 'jquery' ;
import { htmlEscape } from 'escape-goat' ;
import attachTribute from './tribute.js' ;
import { createCommentEasyMDE , getAttachedEasyMDE } from './comp/EasyMDE.js' ;
import { initCompImagePaste } from './comp/ImagePaste.js' ;
import { initCompMarkupContentPreviewTab } from './comp/MarkupContentPreview.js' ;
const { appSubUrl , csrfToken } = window . config ;
export function initRepoIssueTimeTracking ( ) {
$ ( document ) . on ( 'click' , '.issue-add-time' , ( ) => {
$ ( '.issue-start-time-modal' ) . modal ( {
duration : 200 ,
onApprove ( ) {
$ ( '#add_time_manual_form' ) . trigger ( 'submit' ) ;
} ,
} ) . modal ( 'show' ) ;
$ ( '.issue-start-time-modal input' ) . on ( 'keydown' , ( e ) => {
if ( ( e . keyCode || e . key ) === 13 ) {
$ ( '#add_time_manual_form' ) . trigger ( 'submit' ) ;
}
} ) ;
} ) ;
$ ( document ) . on ( 'click' , '.issue-start-time, .issue-stop-time' , ( ) => {
$ ( '#toggle_stopwatch_form' ) . trigger ( 'submit' ) ;
} ) ;
$ ( document ) . on ( 'click' , '.issue-cancel-time' , ( ) => {
$ ( '#cancel_stopwatch_form' ) . trigger ( 'submit' ) ;
} ) ;
$ ( document ) . on ( 'click' , 'button.issue-delete-time' , function ( ) {
const sel = ` .issue-delete-time-modal[data-id=" ${ $ ( this ) . data ( 'id' ) } "] ` ;
$ ( sel ) . modal ( {
duration : 200 ,
onApprove ( ) {
$ ( ` ${ sel } form ` ) . trigger ( 'submit' ) ;
} ,
} ) . modal ( 'show' ) ;
} ) ;
}
function updateDeadline ( deadlineString ) {
$ ( '#deadline-err-invalid-date' ) . hide ( ) ;
$ ( '#deadline-loader' ) . addClass ( 'loading' ) ;
let realDeadline = null ;
if ( deadlineString !== '' ) {
const newDate = Date . parse ( deadlineString ) ;
if ( Number . isNaN ( newDate ) ) {
$ ( '#deadline-loader' ) . removeClass ( 'loading' ) ;
$ ( '#deadline-err-invalid-date' ) . show ( ) ;
return false ;
}
realDeadline = new Date ( newDate ) ;
}
$ . ajax ( ` ${ $ ( '#update-issue-deadline-form' ) . attr ( 'action' ) } ` , {
data : JSON . stringify ( {
due _date : realDeadline ,
} ) ,
headers : {
'X-Csrf-Token' : csrfToken ,
} ,
contentType : 'application/json' ,
type : 'POST' ,
success ( ) {
window . location . reload ( ) ;
} ,
error ( ) {
$ ( '#deadline-loader' ) . removeClass ( 'loading' ) ;
$ ( '#deadline-err-invalid-date' ) . show ( ) ;
} ,
} ) ;
}
export function initRepoIssueDue ( ) {
$ ( document ) . on ( 'click' , '.issue-due-edit' , ( ) => {
$ ( '#deadlineForm' ) . fadeToggle ( 150 ) ;
} ) ;
$ ( document ) . on ( 'click' , '.issue-due-remove' , ( ) => {
updateDeadline ( '' ) ;
} ) ;
$ ( document ) . on ( 'submit' , '.issue-due-form' , ( ) => {
updateDeadline ( $ ( '#deadlineDate' ) . val ( ) ) ;
return false ;
} ) ;
}
export function initRepoIssueList ( ) {
const repolink = $ ( '#repolink' ) . val ( ) ;
const repoId = $ ( '#repoId' ) . val ( ) ;
const crossRepoSearch = $ ( '#crossRepoSearch' ) . val ( ) ;
const tp = $ ( '#type' ) . val ( ) ;
let issueSearchUrl = ` ${ appSubUrl } / ${ repolink } /issues/search?q={query}&type= ${ tp } ` ;
if ( crossRepoSearch === 'true' ) {
issueSearchUrl = ` ${ appSubUrl } /issues/search?q={query}&priority_repo_id= ${ repoId } &type= ${ tp } ` ;
}
$ ( '#new-dependency-drop-list' )
. dropdown ( {
apiSettings : {
url : issueSearchUrl ,
onResponse ( response ) {
const filteredResponse = { success : true , results : [ ] } ;
const currIssueId = $ ( '#new-dependency-drop-list' ) . data ( 'issue-id' ) ;
// Parse the response from the api to work with our dropdown
$ . each ( response , ( _i , issue ) => {
// Don't list current issue in the dependency list.
if ( issue . id === currIssueId ) {
return ;
}
filteredResponse . results . push ( {
name : ` # ${ issue . number } ${ htmlEscape ( issue . title )
} < div class = "text small dont-break-out" > $ { htmlEscape ( issue . repository . full _name ) } < / d i v > ` ,
value : issue . id ,
} ) ;
} ) ;
return filteredResponse ;
} ,
cache : false ,
} ,
fullTextSearch : true ,
} ) ;
function excludeLabel ( item ) {
const href = $ ( item ) . attr ( 'href' ) ;
const id = $ ( item ) . data ( 'label-id' ) ;
const regStr = ` labels=((?:-?[0-9]+%2c)*)( ${ id } )((?:%2c-?[0-9]+)*)& ` ;
const newStr = 'labels=$1-$2$3&' ;
window . location = href . replace ( new RegExp ( regStr ) , newStr ) ;
}
$ ( '.menu a.label-filter-item' ) . each ( function ( ) {
$ ( this ) . on ( 'click' , function ( e ) {
if ( e . altKey ) {
e . preventDefault ( ) ;
excludeLabel ( this ) ;
}
} ) ;
} ) ;
$ ( '.menu .ui.dropdown.label-filter' ) . on ( 'keydown' , ( e ) => {
if ( e . altKey && e . keyCode === 13 ) {
const selectedItems = $ ( '.menu .ui.dropdown.label-filter .menu .item.selected' ) ;
if ( selectedItems . length > 0 ) {
excludeLabel ( $ ( selectedItems [ 0 ] ) ) ;
}
}
} ) ;
}
export function initRepoIssueCommentDelete ( ) {
// Delete comment
$ ( document ) . on ( 'click' , '.delete-comment' , function ( ) {
const $this = $ ( this ) ;
if ( window . confirm ( $this . data ( 'locale' ) ) ) {
$ . post ( $this . data ( 'url' ) , {
_csrf : csrfToken ,
} ) . done ( ( ) => {
const $conversationHolder = $this . closest ( '.conversation-holder' ) ;
// Check if this was a pending comment.
if ( $conversationHolder . find ( '.pending-label' ) . length ) {
const $counter = $ ( '#review-box .review-comments-counter' ) ;
let num = parseInt ( $counter . attr ( 'data-pending-comment-number' ) ) - 1 || 0 ;
num = Math . max ( num , 0 ) ;
$counter . attr ( 'data-pending-comment-number' , num ) ;
$counter . text ( num ) ;
}
$ ( ` # ${ $this . data ( 'comment-id' ) } ` ) . remove ( ) ;
if ( $conversationHolder . length && ! $conversationHolder . find ( '.comment' ) . length ) {
const path = $conversationHolder . data ( 'path' ) ;
const side = $conversationHolder . data ( 'side' ) ;
const idx = $conversationHolder . data ( 'idx' ) ;
const lineType = $conversationHolder . closest ( 'tr' ) . data ( 'line-type' ) ;
if ( lineType === 'same' ) {
$ ( ` [data-path=" ${ path } "] a.add-code-comment[data-idx=" ${ idx } "] ` ) . removeClass ( 'invisible' ) ;
} else {
$ ( ` [data-path=" ${ path } "] a.add-code-comment[data-side=" ${ side } "][data-idx=" ${ idx } "] ` ) . removeClass ( 'invisible' ) ;
}
$conversationHolder . remove ( ) ;
}
} ) ;
}
return false ;
} ) ;
}
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 ) . on ( 'click' , '.cancel-code-comment' , ( e ) => {
const form = $ ( e . currentTarget ) . closest ( 'form' ) ;
if ( form . length > 0 && form . hasClass ( 'comment-form' ) ) {
form . addClass ( 'hide' ) ;
form . closest ( '.comment-code-cloud' ) . find ( 'button.comment-form-reply' ) . show ( ) ;
} else {
form . closest ( '.comment-code-cloud' ) . remove ( ) ;
}
} ) ;
}
export function initRepoIssueStatusButton ( ) {
// Change status
const $statusButton = $ ( '#status-button' ) ;
$ ( '#comment-form textarea' ) . on ( 'keyup' , function ( ) {
const easyMDE = getAttachedEasyMDE ( this ) ;
const value = easyMDE ? . value ( ) || $ ( this ) . val ( ) ;
$statusButton . text ( $statusButton . data ( value . length === 0 ? 'status' : 'status-and-comment' ) ) ;
} ) ;
$statusButton . on ( 'click' , ( ) => {
$ ( '#status' ) . val ( $statusButton . data ( 'status-val' ) ) ;
$ ( '#comment-form' ) . trigger ( 'submit' ) ;
} ) ;
}
export function initRepoPullRequestMerge ( ) {
// Pull Request merge button
const $mergeButton = $ ( '.merge-button > button' ) ;
$mergeButton . on ( 'click' , function ( e ) {
e . preventDefault ( ) ;
$ ( ` . ${ $ ( this ) . data ( 'do' ) } -fields ` ) . show ( ) ;
$ ( this ) . parent ( ) . hide ( ) ;
$ ( '.instruct-toggle' ) . hide ( ) ;
$ ( '.instruct-content' ) . hide ( ) ;
} ) ;
$ ( '.merge-button > .dropdown' ) . dropdown ( {
onChange ( _text , _value , $choice ) {
if ( $choice . data ( 'do' ) ) {
$mergeButton . find ( '.button-text' ) . text ( $choice . text ( ) ) ;
$mergeButton . data ( 'do' , $choice . data ( 'do' ) ) ;
}
}
} ) ;
$ ( '.merge-cancel' ) . on ( 'click' , function ( e ) {
e . preventDefault ( ) ;
$ ( this ) . closest ( '.form' ) . hide ( ) ;
$mergeButton . parent ( ) . show ( ) ;
$ ( '.instruct-toggle' ) . show ( ) ;
} ) ;
}
export function initRepoPullRequestUpdate ( ) {
// Pull Request update button
const $pullUpdateButton = $ ( '.update-button > button' ) ;
$pullUpdateButton . on ( 'click' , function ( e ) {
e . preventDefault ( ) ;
const $this = $ ( this ) ;
const redirect = $this . data ( 'redirect' ) ;
$this . addClass ( 'loading' ) ;
$ . post ( $this . data ( 'do' ) , {
_csrf : csrfToken
} ) . done ( ( data ) => {
if ( data . redirect ) {
window . location . href = data . redirect ;
} else if ( redirect ) {
window . location . href = redirect ;
} else {
window . location . reload ( ) ;
}
} ) ;
} ) ;
$ ( '.update-button > .dropdown' ) . dropdown ( {
onChange ( _text , _value , $choice ) {
const $url = $choice . data ( 'do' ) ;
if ( $url ) {
$pullUpdateButton . find ( '.button-text' ) . text ( $choice . text ( ) ) ;
$pullUpdateButton . data ( 'do' , $url ) ;
}
}
} ) ;
}
export function initRepoPullRequestMergeInstruction ( ) {
$ ( '.show-instruction' ) . on ( 'click' , ( ) => {
$ ( '.instruct-content' ) . toggle ( ) ;
} ) ;
}
export function initRepoPullRequestAllowMaintainerEdit ( ) {
const $checkbox = $ ( '#allow-edits-from-maintainers' ) ;
if ( ! $checkbox . length ) return ;
const promptTip = $checkbox . attr ( 'data-prompt-tip' ) ;
const promptError = $checkbox . attr ( 'data-prompt-error' ) ;
$checkbox . popup ( { content : promptTip } ) ;
$checkbox . checkbox ( {
'onChange' : ( ) => {
const checked = $checkbox . checkbox ( 'is checked' ) ;
let url = $checkbox . attr ( 'data-url' ) ;
url += '/set_allow_maintainer_edit' ;
$checkbox . checkbox ( 'set disabled' ) ;
$ . ajax ( { url , type : 'POST' ,
data : { _csrf : csrfToken , allow _maintainer _edit : checked } ,
error : ( ) => {
$checkbox . popup ( {
content : promptError ,
onHidden : ( ) => {
// the error popup should be shown only once, then we restore the popup to the default message
$checkbox . popup ( { content : promptTip } ) ;
} ,
} ) ;
$checkbox . popup ( 'show' ) ;
} ,
complete : ( ) => {
$checkbox . checkbox ( 'set enabled' ) ;
} ,
} ) ;
} ,
} ) ;
}
export function initRepoIssueReferenceRepositorySearch ( ) {
$ ( '.issue_reference_repository_search' )
. dropdown ( {
apiSettings : {
url : ` ${ appSubUrl } /repo/search?q={query}&limit=20 ` ,
onResponse ( response ) {
const filteredResponse = { success : true , results : [ ] } ;
$ . each ( response . data , ( _r , repo ) => {
filteredResponse . results . push ( {
name : htmlEscape ( repo . full _name ) ,
value : repo . full _name
} ) ;
} ) ;
return filteredResponse ;
} ,
cache : false ,
} ,
onChange ( _value , _text , $choice ) {
const $form = $choice . closest ( 'form' ) ;
$form . attr ( 'action' , ` ${ appSubUrl } / ${ _text } /issues/new ` ) ;
} ,
fullTextSearch : true
} ) ;
}
export function initRepoIssueWipTitle ( ) {
$ ( '.title_wip_desc > a' ) . on ( 'click' , ( e ) => {
e . preventDefault ( ) ;
const $issueTitle = $ ( '#issue_title' ) ;
$issueTitle . focus ( ) ;
const value = $issueTitle . val ( ) . 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 async function updateIssuesMeta ( url , action , issueIds , elementId ) {
return $ . ajax ( {
type : 'POST' ,
url ,
data : {
_csrf : csrfToken ,
action ,
issue _ids : issueIds ,
id : elementId ,
} ,
} ) ;
}
export function initRepoIssueComments ( ) {
if ( $ ( '.repository.view.issue .timeline' ) . length === 0 ) return ;
$ ( '.re-request-review' ) . on ( 'click' , function ( e ) {
e . preventDefault ( ) ;
const url = $ ( this ) . data ( 'update-url' ) ;
const issueId = $ ( this ) . data ( 'issue-id' ) ;
const id = $ ( this ) . data ( 'id' ) ;
const isChecked = $ ( this ) . hasClass ( 'checked' ) ;
updateIssuesMeta (
url ,
isChecked ? 'detach' : 'attach' ,
issueId ,
id ,
) . then ( ( ) => window . location . reload ( ) ) ;
} ) ;
$ ( '.dismiss-review-btn' ) . on ( 'click' , function ( e ) {
e . preventDefault ( ) ;
const $this = $ ( this ) ;
const $dismissReviewModal = $this . next ( ) ;
$dismissReviewModal . modal ( 'show' ) ;
} ) ;
$ ( document ) . on ( 'click' , ( event ) => {
const urlTarget = $ ( ':target' ) ;
if ( urlTarget . length === 0 ) return ;
const urlTargetId = urlTarget . attr ( 'id' ) ;
if ( ! urlTargetId ) return ;
if ( ! /^(issue|pull)(comment)?-\d+$/ . test ( urlTargetId ) ) return ;
const $target = $ ( event . target ) ;
if ( $target . closest ( ` # ${ urlTargetId } ` ) . length === 0 ) {
const scrollPosition = $ ( window ) . scrollTop ( ) ;
window . location . hash = '' ;
$ ( window ) . scrollTop ( scrollPosition ) ;
window . history . pushState ( null , null , ' ' ) ;
}
} ) ;
}
function assignMenuAttributes ( menu ) {
const id = Math . floor ( Math . random ( ) * Math . floor ( 1000000 ) ) ;
menu . attr ( 'data-write' , menu . attr ( 'data-write' ) + id ) ;
menu . attr ( 'data-preview' , menu . attr ( 'data-preview' ) + id ) ;
menu . find ( '.item' ) . each ( function ( ) {
const tab = $ ( this ) . attr ( 'data-tab' ) + id ;
$ ( this ) . attr ( 'data-tab' , tab ) ;
} ) ;
menu . parent ( ) . find ( "*[data-tab='write']" ) . attr ( 'data-tab' , ` write ${ id } ` ) ;
menu . parent ( ) . find ( "*[data-tab='preview']" ) . attr ( 'data-tab' , ` preview ${ id } ` ) ;
initCompMarkupContentPreviewTab ( menu . parent ( '.form' ) ) ;
return id ;
}
export function initRepoPullRequestReview ( ) {
if ( window . location . hash && window . location . hash . startsWith ( '#issuecomment-' ) ) {
const commentDiv = $ ( window . location . hash ) ;
if ( commentDiv ) {
// get the name of the parent id
const groupID = commentDiv . closest ( 'div[id^="code-comments-"]' ) . attr ( 'id' ) ;
if ( groupID && groupID . startsWith ( 'code-comments-' ) ) {
const id = groupID . slice ( 14 ) ;
$ ( ` #show-outdated- ${ id } ` ) . addClass ( 'hide' ) ;
$ ( ` #code-comments- ${ id } ` ) . removeClass ( 'hide' ) ;
$ ( ` #code-preview- ${ id } ` ) . removeClass ( 'hide' ) ;
$ ( ` #hide-outdated- ${ id } ` ) . removeClass ( 'hide' ) ;
commentDiv [ 0 ] . scrollIntoView ( ) ;
}
}
}
$ ( document ) . on ( 'click' , '.show-outdated' , function ( e ) {
e . preventDefault ( ) ;
const id = $ ( this ) . data ( 'comment' ) ;
$ ( this ) . addClass ( 'hide' ) ;
$ ( ` #code-comments- ${ id } ` ) . removeClass ( 'hide' ) ;
$ ( ` #code-preview- ${ id } ` ) . removeClass ( 'hide' ) ;
$ ( ` #hide-outdated- ${ id } ` ) . removeClass ( 'hide' ) ;
} ) ;
$ ( document ) . on ( 'click' , '.hide-outdated' , function ( e ) {
e . preventDefault ( ) ;
const id = $ ( this ) . data ( 'comment' ) ;
$ ( this ) . addClass ( 'hide' ) ;
$ ( ` #code-comments- ${ id } ` ) . addClass ( 'hide' ) ;
$ ( ` #code-preview- ${ id } ` ) . addClass ( 'hide' ) ;
$ ( ` #show-outdated- ${ id } ` ) . removeClass ( 'hide' ) ;
} ) ;
$ ( document ) . on ( 'click' , 'button.comment-form-reply' , async function ( e ) {
e . preventDefault ( ) ;
$ ( this ) . hide ( ) ;
const form = $ ( this ) . closest ( '.comment-code-cloud' ) . find ( '.comment-form' ) ;
form . removeClass ( 'hide' ) ;
const $textarea = form . find ( 'textarea' ) ;
let easyMDE = getAttachedEasyMDE ( $textarea ) ;
if ( ! easyMDE ) {
await attachTribute ( $textarea . get ( ) , { mentions : true , emoji : true } ) ;
easyMDE = await createCommentEasyMDE ( $textarea ) ;
}
$textarea . focus ( ) ;
easyMDE . codemirror . focus ( ) ;
assignMenuAttributes ( form . find ( '.menu' ) ) ;
} ) ;
const $reviewBox = $ ( '.review-box' ) ;
if ( $reviewBox . length === 1 ) {
( async ( ) => {
// the editor's height is too large in some cases, and the panel cannot be scrolled with page now because there is `.repository .diff-detail-box.sticky { position: sticky; }`
// the temporary solution is to make the editor's height smaller (about 4 lines). GitHub also only show 4 lines for default. We can improve the UI (including Dropzone area) in future
// EasyMDE's options can not handle minHeight & maxHeight together correctly, we have to set max-height for .CodeMirror-scroll in CSS.
await createCommentEasyMDE ( $reviewBox . find ( 'textarea' ) , { minHeight : '80px' } ) ;
initCompImagePaste ( $reviewBox ) ;
} ) ( ) ;
}
// The following part is only for diff views
if ( $ ( '.repository.pull.diff' ) . length === 0 ) {
return ;
}
$ ( '.btn-review' ) . on ( 'click' , function ( e ) {
e . preventDefault ( ) ;
$ ( this ) . closest ( '.dropdown' ) . find ( '.menu' ) . toggle ( 'visible' ) ;
} ) . closest ( '.dropdown' ) . find ( '.close' ) . on ( 'click' , function ( e ) {
e . preventDefault ( ) ;
$ ( this ) . closest ( '.menu' ) . toggle ( 'visible' ) ;
} ) ;
$ ( document ) . on ( 'click' , 'a.add-code-comment' , async function ( e ) {
if ( $ ( e . target ) . hasClass ( 'btn-add-single' ) ) return ; // https://github.com/go-gitea/gitea/issues/4745
e . preventDefault ( ) ;
const isSplit = $ ( this ) . closest ( '.code-diff' ) . hasClass ( 'code-diff-split' ) ;
const side = $ ( this ) . data ( 'side' ) ;
const idx = $ ( this ) . data ( 'idx' ) ;
const path = $ ( this ) . closest ( '[data-path]' ) . data ( 'path' ) ;
const tr = $ ( this ) . closest ( 'tr' ) ;
const lineType = tr . data ( 'line-type' ) ;
let ntr = tr . next ( ) ;
if ( ! ntr . hasClass ( 'add-comment' ) ) {
ntr = $ ( `
< tr class = "add-comment" data - line - type = "${lineType}" >
$ { isSplit ? `
< td class = "lines-num" > < / t d >
< td class = "lines-escape" > < / t d >
< td class = "lines-type-marker" > < / t d >
< td class = "add-comment-left" > < / t d >
< td class = "lines-num" > < / t d >
< td class = "lines-escape" > < / t d >
< td class = "lines-type-marker" > < / t d >
< td class = "add-comment-right" > < / t d >
` : `
< td class = "lines-num" > < / t d >
< td class = "lines-num" > < / t d >
< td class = "lines-escape" > < / t d >
< td class = "add-comment-left add-comment-right" colspan = "2" > < / t d >
` }
< / t r > ` ) ;
tr . after ( ntr ) ;
}
const td = ntr . find ( ` .add-comment- ${ side } ` ) ;
let commentCloud = td . find ( '.comment-code-cloud' ) ;
if ( commentCloud . length === 0 && ! ntr . find ( 'button[name="is_review"]' ) . length ) {
const data = await $ . get ( $ ( this ) . closest ( '[data-new-comment-url]' ) . data ( 'new-comment-url' ) ) ;
td . html ( data ) ;
commentCloud = td . find ( '.comment-code-cloud' ) ;
assignMenuAttributes ( commentCloud . find ( '.menu' ) ) ;
td . find ( "input[name='line']" ) . val ( idx ) ;
td . find ( "input[name='side']" ) . val ( side === 'left' ? 'previous' : 'proposed' ) ;
td . find ( "input[name='path']" ) . val ( path ) ;
const $textarea = commentCloud . find ( 'textarea' ) ;
await attachTribute ( $textarea . get ( ) , { mentions : true , emoji : true } ) ;
const easyMDE = await createCommentEasyMDE ( $textarea ) ;
$textarea . focus ( ) ;
easyMDE . codemirror . focus ( ) ;
}
} ) ;
}
export function initRepoIssueReferenceIssue ( ) {
// Reference issue
$ ( document ) . on ( 'click' , '.reference-issue' , function ( event ) {
const $this = $ ( this ) ;
$this . closest ( '.dropdown' ) . find ( '.menu' ) . toggle ( 'visible' ) ;
const content = $ ( ` #comment- ${ $this . data ( 'target' ) } ` ) . text ( ) ;
const poster = $this . data ( 'poster-username' ) ;
const reference = $this . data ( 'reference' ) ;
const $modal = $ ( $this . data ( 'modal' ) ) ;
$modal . find ( 'textarea[name="content"]' ) . val ( ` ${ content } \n \n _Originally posted by @ ${ poster } in ${ reference } _ ` ) ;
$modal . modal ( 'show' ) ;
event . preventDefault ( ) ;
} ) ;
}
export function initRepoIssueWipToggle ( ) {
// Toggle WIP
$ ( '.toggle-wip a, .toggle-wip button' ) . on ( 'click' , async ( e ) => {
e . preventDefault ( ) ;
const toggleWip = e . currentTarget . closest ( '.toggle-wip' ) ;
const title = toggleWip . getAttribute ( 'data-title' ) ;
const wipPrefix = toggleWip . getAttribute ( 'data-wip-prefix' ) ;
const updateUrl = toggleWip . getAttribute ( 'data-update-url' ) ;
await $ . post ( updateUrl , {
_csrf : csrfToken ,
title : title ? . startsWith ( wipPrefix ) ? title . slice ( wipPrefix . length ) . trim ( ) : ` ${ wipPrefix . trim ( ) } ${ title } ` ,
} ) ;
window . location . reload ( ) ;
} ) ;
}
export function initRepoIssueTitleEdit ( ) {
// Edit issue title
const $issueTitle = $ ( '#issue-title' ) ;
const $editInput = $ ( '#edit-title-input input' ) ;
const editTitleToggle = function ( ) {
$issueTitle . toggle ( ) ;
$ ( '.not-in-edit' ) . toggle ( ) ;
$ ( '#edit-title-input' ) . toggle ( ) ;
$ ( '#pull-desc' ) . toggle ( ) ;
$ ( '#pull-desc-edit' ) . toggle ( ) ;
$ ( '.in-edit' ) . toggle ( ) ;
$ ( '#issue-title-wrapper' ) . toggleClass ( 'edit-active' ) ;
$editInput . focus ( ) ;
return false ;
} ;
$ ( '#edit-title' ) . on ( 'click' , editTitleToggle ) ;
$ ( '#cancel-edit-title' ) . on ( 'click' , editTitleToggle ) ;
$ ( '#save-edit-title' ) . on ( 'click' , editTitleToggle ) . on ( 'click' , function ( ) {
const pullrequest _targetbranch _change = function ( update _url ) {
const targetBranch = $ ( '#pull-target-branch' ) . data ( 'branch' ) ;
const $branchTarget = $ ( '#branch_target' ) ;
if ( targetBranch === $branchTarget . text ( ) ) {
return false ;
}
$ . post ( update _url , {
_csrf : csrfToken ,
target _branch : targetBranch
} ) . done ( ( data ) => {
$branchTarget . text ( data . base _branch ) ;
} ) . always ( ( ) => {
window . location . reload ( ) ;
} ) ;
} ;
const pullrequest _target _update _url = $ ( this ) . data ( 'target-update-url' ) ;
if ( $editInput . val ( ) . length === 0 || $editInput . val ( ) === $issueTitle . text ( ) ) {
$editInput . val ( $issueTitle . text ( ) ) ;
pullrequest _targetbranch _change ( pullrequest _target _update _url ) ;
} else {
$ . post ( $ ( this ) . data ( 'update-url' ) , {
_csrf : csrfToken ,
title : $editInput . val ( )
} , ( data ) => {
$editInput . val ( data . title ) ;
$issueTitle . text ( data . title ) ;
pullrequest _targetbranch _change ( pullrequest _target _update _url ) ;
window . location . reload ( ) ;
} ) ;
}
return false ;
} ) ;
}
export function initRepoIssueBranchSelect ( ) {
const changeBranchSelect = function ( ) {
const selectionTextField = $ ( '#pull-target-branch' ) ;
const baseName = selectionTextField . data ( 'basename' ) ;
const branchNameNew = $ ( this ) . data ( 'branch' ) ;
const branchNameOld = selectionTextField . data ( 'branch' ) ;
// Replace branch name to keep translation from HTML template
selectionTextField . html ( selectionTextField . html ( ) . replace (
` ${ baseName } : ${ branchNameOld } ` ,
` ${ baseName } : ${ branchNameNew } `
) ) ;
selectionTextField . data ( 'branch' , branchNameNew ) ; // update branch name in setting
} ;
$ ( '#branch-select > .item' ) . on ( 'click' , changeBranchSelect ) ;
}