@ -29,11 +29,6 @@ import {initRepoSettingBranches} from './repo-settings.js';
const { csrfToken } = window . config ;
const { csrfToken } = window . config ;
const commentMDEditors = { } ;
// FIXME: the usage of `autoSimpleMDE` is quite messy, the refactor should be done very carefully in future.
let autoSimpleMDE ;
export function initRepoCommentForm ( ) {
export function initRepoCommentForm ( ) {
if ( $ ( '.comment.form' ) . length === 0 ) {
if ( $ ( '.comment.form' ) . length === 0 ) {
return ;
return ;
@ -68,12 +63,12 @@ export function initRepoCommentForm() {
} ) ;
} ) ;
}
}
autoSimpleMDE = createCommentSimpleMDE ( $ ( '.comment.form textarea:not(.review-textarea)' ) ) ;
createCommentSimpleMDE ( $ ( '.comment.form textarea:not(.review-textarea)' ) ) ;
initBranchSelector ( ) ;
initBranchSelector ( ) ;
initCompMarkupContentPreviewTab ( $ ( '.comment.form' ) ) ;
initCompMarkupContentPreviewTab ( $ ( '.comment.form' ) ) ;
initCompImagePaste ( $ ( '.comment.form' ) ) ;
initCompImagePaste ( $ ( '.comment.form' ) ) ;
// Listsubmit
// List submits
function initListSubmits ( selector , outerSelector ) {
function initListSubmits ( selector , outerSelector ) {
const $list = $ ( ` .ui. ${ outerSelector } .list ` ) ;
const $list = $ ( ` .ui. ${ outerSelector } .list ` ) ;
const $noSelect = $list . find ( '.no-select' ) ;
const $noSelect = $list . find ( '.no-select' ) ;
@ -259,6 +254,163 @@ export function initRepoCommentForm() {
}
}
async function onEditContent ( event ) {
event . preventDefault ( ) ;
$ ( this ) . closest ( '.dropdown' ) . find ( '.menu' ) . toggle ( 'visible' ) ;
const $segment = $ ( this ) . closest ( '.header' ) . next ( ) ;
const $editContentZone = $segment . find ( '.edit-content-zone' ) ;
const $renderContent = $segment . find ( '.render-content' ) ;
const $rawContent = $segment . find ( '.raw-content' ) ;
let $textarea ;
let $simplemde ;
// Setup new form
if ( $editContentZone . html ( ) . length === 0 ) {
$editContentZone . html ( $ ( '#edit-content-form' ) . html ( ) ) ;
$textarea = $editContentZone . find ( 'textarea' ) ;
await attachTribute ( $textarea . get ( ) , { mentions : true , emoji : true } ) ;
let dz ;
const $dropzone = $editContentZone . find ( '.dropzone' ) ;
if ( $dropzone . length === 1 ) {
$dropzone . data ( 'saved' , false ) ;
const fileUuidDict = { } ;
dz = await createDropzone ( $dropzone [ 0 ] , {
url : $dropzone . data ( 'upload-url' ) ,
headers : { 'X-Csrf-Token' : csrfToken } ,
maxFiles : $dropzone . data ( 'max-file' ) ,
maxFilesize : $dropzone . data ( 'max-size' ) ,
acceptedFiles : ( [ '*/*' , '' ] . includes ( $dropzone . data ( 'accepts' ) ) ) ? null : $dropzone . data ( 'accepts' ) ,
addRemoveLinks : true ,
dictDefaultMessage : $dropzone . data ( 'default-message' ) ,
dictInvalidFileType : $dropzone . data ( 'invalid-input-type' ) ,
dictFileTooBig : $dropzone . data ( 'file-too-big' ) ,
dictRemoveFile : $dropzone . data ( 'remove-file' ) ,
timeout : 0 ,
thumbnailMethod : 'contain' ,
thumbnailWidth : 480 ,
thumbnailHeight : 480 ,
init ( ) {
this . on ( 'success' , ( file , data ) => {
fileUuidDict [ file . uuid ] = { submitted : false } ;
const input = $ ( ` <input id=" ${ data . uuid } " name="files" type="hidden"> ` ) . val ( data . uuid ) ;
$dropzone . find ( '.files' ) . append ( input ) ;
} ) ;
this . on ( 'removedfile' , ( file ) => {
$ ( ` # ${ file . uuid } ` ) . remove ( ) ;
if ( $dropzone . data ( 'remove-url' ) && ! fileUuidDict [ file . uuid ] . submitted ) {
$ . post ( $dropzone . data ( 'remove-url' ) , {
file : file . uuid ,
_csrf : csrfToken ,
} ) ;
}
} ) ;
this . on ( 'submit' , ( ) => {
$ . each ( fileUuidDict , ( fileUuid ) => {
fileUuidDict [ fileUuid ] . submitted = true ;
} ) ;
} ) ;
this . on ( 'reload' , ( ) => {
$ . getJSON ( $editContentZone . data ( 'attachment-url' ) , ( data ) => {
dz . removeAllFiles ( true ) ;
$dropzone . find ( '.files' ) . empty ( ) ;
$ . each ( data , function ( ) {
const imgSrc = ` ${ $dropzone . data ( 'link-url' ) } / ${ this . uuid } ` ;
dz . emit ( 'addedfile' , this ) ;
dz . emit ( 'thumbnail' , this , imgSrc ) ;
dz . emit ( 'complete' , this ) ;
dz . files . push ( this ) ;
fileUuidDict [ this . uuid ] = { submitted : true } ;
$dropzone . find ( ` img[src=' ${ imgSrc } '] ` ) . css ( 'max-width' , '100%' ) ;
const input = $ ( ` <input id=" ${ this . uuid } " name="files" type="hidden"> ` ) . val ( this . uuid ) ;
$dropzone . find ( '.files' ) . append ( input ) ;
} ) ;
} ) ;
} ) ;
} ,
} ) ;
dz . emit ( 'reload' ) ;
}
// Give new write/preview data-tab name to distinguish from others
const $editContentForm = $editContentZone . find ( '.ui.comment.form' ) ;
const $tabMenu = $editContentForm . find ( '.tabular.menu' ) ;
$tabMenu . attr ( 'data-write' , $editContentZone . data ( 'write' ) ) ;
$tabMenu . attr ( 'data-preview' , $editContentZone . data ( 'preview' ) ) ;
$tabMenu . find ( '.write.item' ) . attr ( 'data-tab' , $editContentZone . data ( 'write' ) ) ;
$tabMenu . find ( '.preview.item' ) . attr ( 'data-tab' , $editContentZone . data ( 'preview' ) ) ;
$editContentForm . find ( '.write' ) . attr ( 'data-tab' , $editContentZone . data ( 'write' ) ) ;
$editContentForm . find ( '.preview' ) . attr ( 'data-tab' , $editContentZone . data ( 'preview' ) ) ;
$simplemde = createCommentSimpleMDE ( $textarea ) ;
initCompMarkupContentPreviewTab ( $editContentForm ) ;
if ( $dropzone . length === 1 ) {
initSimpleMDEImagePaste ( $simplemde , $dropzone [ 0 ] , $dropzone . find ( '.files' ) ) ;
}
$editContentZone . find ( '.cancel.button' ) . on ( 'click' , ( ) => {
$renderContent . show ( ) ;
$editContentZone . hide ( ) ;
if ( dz ) {
dz . emit ( 'reload' ) ;
}
} ) ;
$editContentZone . find ( '.save.button' ) . on ( 'click' , ( ) => {
$renderContent . show ( ) ;
$editContentZone . hide ( ) ;
const $attachments = $dropzone . find ( '.files' ) . find ( '[name=files]' ) . map ( function ( ) {
return $ ( this ) . val ( ) ;
} ) . get ( ) ;
$ . post ( $editContentZone . data ( 'update-url' ) , {
_csrf : csrfToken ,
content : $textarea . val ( ) ,
context : $editContentZone . data ( 'context' ) ,
files : $attachments ,
} , ( data ) => {
if ( data . length === 0 || data . content . length === 0 ) {
$renderContent . html ( $ ( '#no-content' ) . html ( ) ) ;
$rawContent . text ( '' ) ;
} else {
$renderContent . html ( data . content ) ;
$rawContent . text ( $textarea . val ( ) ) ;
}
const $content = $segment ;
if ( ! $content . find ( '.dropzone-attachments' ) . length ) {
if ( data . attachments !== '' ) {
$content . append ( ` <div class="dropzone-attachments"></div> ` ) ;
$content . find ( '.dropzone-attachments' ) . replaceWith ( data . attachments ) ;
}
} else if ( data . attachments === '' ) {
$content . find ( '.dropzone-attachments' ) . remove ( ) ;
} else {
$content . find ( '.dropzone-attachments' ) . replaceWith ( data . attachments ) ;
}
if ( dz ) {
dz . emit ( 'submit' ) ;
dz . emit ( 'reload' ) ;
}
initMarkupContent ( ) ;
initCommentContent ( ) ;
} ) ;
} ) ;
} else {
$textarea = $segment . find ( 'textarea' ) ;
$simplemde = $textarea . data ( 'simplemde' ) ;
}
// Show write/preview tab and copy raw content as needed
$editContentZone . show ( ) ;
$renderContent . hide ( ) ;
if ( $textarea . val ( ) . length === 0 ) {
$textarea . val ( $rawContent . text ( ) ) ;
$simplemde . value ( $rawContent . text ( ) ) ;
}
requestAnimationFrame ( ( ) => {
$textarea . focus ( ) ;
$simplemde . codemirror . focus ( ) ;
} ) ;
}
export function initRepository ( ) {
export function initRepository ( ) {
if ( $ ( '.repository' ) . length === 0 ) {
if ( $ ( '.repository' ) . length === 0 ) {
return ;
return ;
@ -333,186 +485,29 @@ export function initRepository() {
} ) ;
} ) ;
}
}
// Compare or pull request
const $repoDiff = $ ( '.repository.diff' ) ;
if ( $repoDiff . length ) {
initRepoCommonBranchOrTagDropdown ( '.choose.branch .dropdown' ) ;
initRepoCommonFilterSearchDropdown ( '.choose.branch .dropdown' ) ;
}
initRepoClone ( ) ;
initRepoCommonLanguageStats ( ) ;
initRepoSettingBranches ( ) ;
// Issues
// Issues
if ( $ ( '.repository.view.issue' ) . length > 0 ) {
if ( $ ( '.repository.view.issue' ) . length > 0 ) {
initRepoIssueCommentEdit ( ) ;
initRepoIssueBranchSelect ( ) ;
initRepoIssueBranchSelect ( ) ;
initRepoIssueTitleEdit ( ) ;
initRepoIssueTitleEdit ( ) ;
initRepoIssueWipToggle ( ) ;
initRepoIssueWipToggle ( ) ;
initRepoIssueComments ( ) ;
initRepoIssueComments ( ) ;
// Issue/PR Context Menus
$ ( '.context-dropdown' ) . dropdown ( {
action : 'hide' ,
} ) ;
initRepoDiffConversationNav ( ) ;
initRepoDiffConversationNav ( ) ;
initRepoIssueQuoteReply ( ) ;
initRepoIssueReferenceIssue ( ) ;
initRepoIssueReferenceIssue ( ) ;
// Edit issue or comment content
$ ( document ) . on ( 'click' , '.edit-content' , async function ( event ) {
event . preventDefault ( ) ;
$ ( this ) . closest ( '.dropdown' ) . find ( '.menu' ) . toggle ( 'visible' ) ;
const $segment = $ ( this ) . closest ( '.header' ) . next ( ) ;
const $editContentZone = $segment . find ( '.edit-content-zone' ) ;
const $renderContent = $segment . find ( '.render-content' ) ;
const $rawContent = $segment . find ( '.raw-content' ) ;
let $textarea ;
let $simplemde ;
// Setup new form
if ( $editContentZone . html ( ) . length === 0 ) {
$editContentZone . html ( $ ( '#edit-content-form' ) . html ( ) ) ;
$textarea = $editContentZone . find ( 'textarea' ) ;
await attachTribute ( $textarea . get ( ) , { mentions : true , emoji : true } ) ;
let dz ;
const $dropzone = $editContentZone . find ( '.dropzone' ) ;
if ( $dropzone . length === 1 ) {
$dropzone . data ( 'saved' , false ) ;
const fileUuidDict = { } ;
dz = await createDropzone ( $dropzone [ 0 ] , {
url : $dropzone . data ( 'upload-url' ) ,
headers : { 'X-Csrf-Token' : csrfToken } ,
maxFiles : $dropzone . data ( 'max-file' ) ,
maxFilesize : $dropzone . data ( 'max-size' ) ,
acceptedFiles : ( [ '*/*' , '' ] . includes ( $dropzone . data ( 'accepts' ) ) ) ? null : $dropzone . data ( 'accepts' ) ,
addRemoveLinks : true ,
dictDefaultMessage : $dropzone . data ( 'default-message' ) ,
dictInvalidFileType : $dropzone . data ( 'invalid-input-type' ) ,
dictFileTooBig : $dropzone . data ( 'file-too-big' ) ,
dictRemoveFile : $dropzone . data ( 'remove-file' ) ,
timeout : 0 ,
thumbnailMethod : 'contain' ,
thumbnailWidth : 480 ,
thumbnailHeight : 480 ,
init ( ) {
this . on ( 'success' , ( file , data ) => {
fileUuidDict [ file . uuid ] = {
submitted : false ,
} ;
const input = $ ( ` <input id=" ${ data . uuid } " name="files" type="hidden"> ` ) . val ( data . uuid ) ;
$dropzone . find ( '.files' ) . append ( input ) ;
} ) ;
this . on ( 'removedfile' , ( file ) => {
$ ( ` # ${ file . uuid } ` ) . remove ( ) ;
if ( $dropzone . data ( 'remove-url' ) && ! fileUuidDict [ file . uuid ] . submitted ) {
$ . post ( $dropzone . data ( 'remove-url' ) , {
file : file . uuid ,
_csrf : csrfToken ,
} ) ;
}
} ) ;
this . on ( 'submit' , ( ) => {
$ . each ( fileUuidDict , ( fileUuid ) => {
fileUuidDict [ fileUuid ] . submitted = true ;
} ) ;
} ) ;
this . on ( 'reload' , ( ) => {
$ . getJSON ( $editContentZone . data ( 'attachment-url' ) , ( data ) => {
dz . removeAllFiles ( true ) ;
$dropzone . find ( '.files' ) . empty ( ) ;
$ . each ( data , function ( ) {
const imgSrc = ` ${ $dropzone . data ( 'link-url' ) } / ${ this . uuid } ` ;
dz . emit ( 'addedfile' , this ) ;
dz . emit ( 'thumbnail' , this , imgSrc ) ;
dz . emit ( 'complete' , this ) ;
dz . files . push ( this ) ;
fileUuidDict [ this . uuid ] = {
submitted : true ,
} ;
$dropzone . find ( ` img[src=' ${ imgSrc } '] ` ) . css ( 'max-width' , '100%' ) ;
const input = $ ( ` <input id=" ${ this . uuid } " name="files" type="hidden"> ` ) . val ( this . uuid ) ;
$dropzone . find ( '.files' ) . append ( input ) ;
} ) ;
} ) ;
} ) ;
} ,
} ) ;
dz . emit ( 'reload' ) ;
}
// Give new write/preview data-tab name to distinguish from others
const $editContentForm = $editContentZone . find ( '.ui.comment.form' ) ;
const $tabMenu = $editContentForm . find ( '.tabular.menu' ) ;
$tabMenu . attr ( 'data-write' , $editContentZone . data ( 'write' ) ) ;
$tabMenu . attr ( 'data-preview' , $editContentZone . data ( 'preview' ) ) ;
$tabMenu . find ( '.write.item' ) . attr ( 'data-tab' , $editContentZone . data ( 'write' ) ) ;
$tabMenu . find ( '.preview.item' ) . attr ( 'data-tab' , $editContentZone . data ( 'preview' ) ) ;
$editContentForm . find ( '.write' ) . attr ( 'data-tab' , $editContentZone . data ( 'write' ) ) ;
$editContentForm . find ( '.preview' ) . attr ( 'data-tab' , $editContentZone . data ( 'preview' ) ) ;
$simplemde = createCommentSimpleMDE ( $textarea ) ;
commentMDEditors [ $editContentZone . data ( 'write' ) ] = $simplemde ;
initCompMarkupContentPreviewTab ( $editContentForm ) ;
if ( $dropzone . length === 1 ) {
initSimpleMDEImagePaste ( $simplemde , $dropzone [ 0 ] , $dropzone . find ( '.files' ) ) ;
}
$editContentZone . find ( '.cancel.button' ) . on ( 'click' , ( ) => {
$renderContent . show ( ) ;
$editContentZone . hide ( ) ;
if ( dz ) {
dz . emit ( 'reload' ) ;
}
} ) ;
$editContentZone . find ( '.save.button' ) . on ( 'click' , ( ) => {
$renderContent . show ( ) ;
$editContentZone . hide ( ) ;
const $attachments = $dropzone . find ( '.files' ) . find ( '[name=files]' ) . map ( function ( ) {
return $ ( this ) . val ( ) ;
} ) . get ( ) ;
$ . post ( $editContentZone . data ( 'update-url' ) , {
_csrf : csrfToken ,
content : $textarea . val ( ) ,
context : $editContentZone . data ( 'context' ) ,
files : $attachments ,
} , ( data ) => {
if ( data . length === 0 || data . content . length === 0 ) {
$renderContent . html ( $ ( '#no-content' ) . html ( ) ) ;
$rawContent . text ( '' ) ;
} else {
$renderContent . html ( data . content ) ;
$rawContent . text ( $textarea . val ( ) ) ;
}
const $content = $segment ;
if ( ! $content . find ( '.dropzone-attachments' ) . length ) {
if ( data . attachments !== '' ) {
$content . append ( `
< div class = "dropzone-attachments" >
< / d i v >
` );
$content . find ( '.dropzone-attachments' ) . replaceWith ( data . attachments ) ;
}
} else if ( data . attachments === '' ) {
$content . find ( '.dropzone-attachments' ) . remove ( ) ;
} else {
$content . find ( '.dropzone-attachments' ) . replaceWith ( data . attachments ) ;
}
if ( dz ) {
dz . emit ( 'submit' ) ;
dz . emit ( 'reload' ) ;
}
initMarkupContent ( ) ;
initCommentContent ( ) ;
} ) ;
} ) ;
} else {
$textarea = $segment . find ( 'textarea' ) ;
$simplemde = commentMDEditors [ $editContentZone . data ( 'write' ) ] ;
}
// Show write/preview tab and copy raw content as needed
$editContentZone . show ( ) ;
$renderContent . hide ( ) ;
if ( $textarea . val ( ) . length === 0 ) {
$textarea . val ( $rawContent . text ( ) ) ;
$simplemde . value ( $rawContent . text ( ) ) ;
}
requestAnimationFrame ( ( ) => {
$textarea . focus ( ) ;
$simplemde . codemirror . focus ( ) ;
} ) ;
} ) ;
initRepoIssueCommentDelete ( ) ;
initRepoIssueCommentDelete ( ) ;
initRepoIssueDependencyDelete ( ) ;
initRepoIssueDependencyDelete ( ) ;
@ -523,55 +518,55 @@ export function initRepository() {
initCompReactionSelector ( ) ;
initCompReactionSelector ( ) ;
}
}
initRepoClone ( ) ;
// Compare or pull request
const $repoDiff = $ ( '.repository.diff' ) ;
if ( $repoDiff . length ) {
initRepoCommonBranchOrTagDropdown ( '.choose.branch .dropdown' ) ;
initRepoCommonFilterSearchDropdown ( '.choose.branch .dropdown' ) ;
}
// Pull request
// Pull request
const $repoComparePull = $ ( '.repository.compare.pull' ) ;
const $repoComparePull = $ ( '.repository.compare.pull' ) ;
if ( $repoComparePull . length > 0 ) {
if ( $repoComparePull . length > 0 ) {
// show pull request form
// show pull request form
$repoComparePull . find ( 'button.show-form' ) . on ( 'click' , function ( e ) {
$repoComparePull . find ( 'button.show-form' ) . on ( 'click' , function ( e ) {
e . preventDefault ( ) ;
e . preventDefault ( ) ;
$repoComparePull . find ( '.pullrequest-form' ) . show ( ) ;
autoSimpleMDE . codemirror . refresh ( ) ;
$ ( this ) . parent ( ) . hide ( ) ;
$ ( this ) . parent ( ) . hide ( ) ;
const $form = $repoComparePull . find ( '.pullrequest-form' ) ;
const $simplemde = $form . find ( 'textarea.edit_area' ) . data ( 'simplemde' ) ;
$form . show ( ) ;
$simplemde . codemirror . refresh ( ) ;
} ) ;
} ) ;
}
}
initRepoSettingBranches ( ) ;
initRepoCommonLanguageStats ( ) ;
}
}
function initRepoIssueQuoteReply ( ) {
function initRepoIssueCommentEdit ( ) {
// Issue/PR Context Menus
$ ( '.comment-header-right .context-dropdown' ) . dropdown ( { action : 'hide' } ) ;
// Edit issue or comment content
$ ( document ) . on ( 'click' , '.edit-content' , onEditContent ) ;
// Quote reply
// Quote reply
$ ( document ) . on ( 'click' , '.quote-reply' , function ( event ) {
$ ( document ) . on ( 'click' , '.quote-reply' , function ( event ) {
$ ( this ) . closest ( '.dropdown' ) . find ( '.menu' ) . toggle ( 'visible' ) ;
$ ( this ) . closest ( '.dropdown' ) . find ( '.menu' ) . toggle ( 'visible' ) ;
const target = $ ( this ) . data ( 'target' ) ;
const target = $ ( this ) . data ( 'target' ) ;
const quote = $ ( ` #comment- ${ target } ` ) . text ( ) . replace ( /\n/g , '\n> ' ) ;
const quote = $ ( ` #comment- ${ target } ` ) . text ( ) . replace ( /\n/g , '\n> ' ) ;
const content = ` > ${ quote } \n \n ` ;
const content = ` > ${ quote } \n \n ` ;
let $simplemde = autoSimpleMDE ;
let $simplemde ;
if ( $ ( this ) . hasClass ( 'quote-reply-diff' ) ) {
if ( $ ( this ) . hasClass ( 'quote-reply-diff' ) ) {
const $parent = $ ( this ) . closest ( '.comment-code-cloud' ) ;
const $parent = $ ( this ) . closest ( '.comment-code-cloud' ) ;
$parent . find ( 'button.comment-form-reply' ) . trigger ( 'click' ) ;
$parent . find ( 'button.comment-form-reply' ) . trigger ( 'click' ) ;
$simplemde = $parent . find ( '[name="content"]' ) . data ( 'simplemde' ) ;
$simplemde = $parent . find ( '[name="content"]' ) . data ( 'simplemde' ) ;
} else {
// for normal issue/comment page
$simplemde = $ ( '#comment-form .edit_area' ) . data ( 'simplemde' ) ;
}
}
if ( $simplemde !== null ) {
if ( $simplemde ) {
if ( $simplemde . value ( ) !== '' ) {
if ( $simplemde . value ( ) !== '' ) {
$simplemde . value ( ` ${ $simplemde . value ( ) } \n \n ${ content } ` ) ;
$simplemde . value ( ` ${ $simplemde . value ( ) } \n \n ${ content } ` ) ;
} else {
} else {
$simplemde . value ( ` ${ content } ` ) ;
$simplemde . value ( ` ${ content } ` ) ;
}
}
requestAnimationFrame ( ( ) => {
$simplemde . codemirror . focus ( ) ;
$simplemde . codemirror . setCursor ( $simplemde . codemirror . lineCount ( ) , 0 ) ;
} ) ;
}
}
requestAnimationFrame ( ( ) => {
$simplemde . codemirror . focus ( ) ;
$simplemde . codemirror . setCursor ( $simplemde . codemirror . lineCount ( ) , 0 ) ;
} ) ;
event . preventDefault ( ) ;
event . preventDefault ( ) ;
} ) ;
} ) ;
}
}