loading up the forgejo repo on tangled to test page performance
0
fork

Configure Feed

Select the types of activity you want to include in your feed.

Refactor repo-legacy.js, remove messy global variables. Fix errors. (#17646)

Refactor repo-legacy.js, remove messy global variables. Fix errors.
Fix an error in Sortable
Fix a incorrect call assignMenuAttributes from the template

authored by

wxiaoguang and committed by
GitHub
55be5fe3 e1d65599

+199 -202
+1 -1
README.md
··· 74 74 The `build` target is split into two sub-targets: 75 75 76 76 - `make backend` which requires [Go 1.16](https://golang.org/dl/) or greater. 77 - - `make frontend` which requires [Node.js 12.17](https://nodejs.org/en/download/) or greater and Internet connectivity to download npm dependencies. 77 + - `make frontend` which requires [Node.js LTS](https://nodejs.org/en/download/) or greater and Internet connectivity to download npm dependencies. 78 78 79 79 When building from the official source tarballs which include pre-built frontend files, the `frontend` target will not be triggered, making it possible to build without Node.js and Internet connectivity. 80 80
+1 -1
templates/repo/diff/comment_form.tmpl
··· 9 9 <input type="hidden" name="diff_start_cid"> 10 10 <input type="hidden" name="diff_end_cid"> 11 11 <input type="hidden" name="diff_base_cid"> 12 - <div class="ui top tabular menu" {{if not $.hidden}}onload="assignMenuAttributes(this)" {{end}}data-write="write" data-preview="preview"> 12 + <div class="ui top tabular menu" data-write="write" data-preview="preview"> 13 13 <a class="active item" data-tab="write">{{$.root.i18n.Tr "write"}}</a> 14 14 <a class="item" data-tab="preview" data-url="{{$.root.Repository.APIURL}}/markdown" data-context="{{$.root.RepoLink}}">{{$.root.i18n.Tr "preview"}}</a> 15 15 </div>
+193 -198
web_src/js/features/repo-legacy.js
··· 29 29 30 30 const {csrfToken} = window.config; 31 31 32 - const commentMDEditors = {}; 33 - 34 - // FIXME: the usage of `autoSimpleMDE` is quite messy, the refactor should be done very carefully in future. 35 - let autoSimpleMDE; 36 - 37 32 export function initRepoCommentForm() { 38 33 if ($('.comment.form').length === 0) { 39 34 return; ··· 68 63 }); 69 64 } 70 65 71 - autoSimpleMDE = createCommentSimpleMDE($('.comment.form textarea:not(.review-textarea)')); 66 + createCommentSimpleMDE($('.comment.form textarea:not(.review-textarea)')); 72 67 initBranchSelector(); 73 68 initCompMarkupContentPreviewTab($('.comment.form')); 74 69 initCompImagePaste($('.comment.form')); 75 70 76 - // Listsubmit 71 + // List submits 77 72 function initListSubmits(selector, outerSelector) { 78 73 const $list = $(`.ui.${outerSelector}.list`); 79 74 const $noSelect = $list.find('.no-select'); ··· 259 254 } 260 255 261 256 257 + async function onEditContent(event) { 258 + event.preventDefault(); 259 + $(this).closest('.dropdown').find('.menu').toggle('visible'); 260 + const $segment = $(this).closest('.header').next(); 261 + const $editContentZone = $segment.find('.edit-content-zone'); 262 + const $renderContent = $segment.find('.render-content'); 263 + const $rawContent = $segment.find('.raw-content'); 264 + let $textarea; 265 + let $simplemde; 266 + 267 + // Setup new form 268 + if ($editContentZone.html().length === 0) { 269 + $editContentZone.html($('#edit-content-form').html()); 270 + $textarea = $editContentZone.find('textarea'); 271 + await attachTribute($textarea.get(), {mentions: true, emoji: true}); 272 + 273 + let dz; 274 + const $dropzone = $editContentZone.find('.dropzone'); 275 + if ($dropzone.length === 1) { 276 + $dropzone.data('saved', false); 277 + 278 + const fileUuidDict = {}; 279 + dz = await createDropzone($dropzone[0], { 280 + url: $dropzone.data('upload-url'), 281 + headers: {'X-Csrf-Token': csrfToken}, 282 + maxFiles: $dropzone.data('max-file'), 283 + maxFilesize: $dropzone.data('max-size'), 284 + acceptedFiles: (['*/*', ''].includes($dropzone.data('accepts'))) ? null : $dropzone.data('accepts'), 285 + addRemoveLinks: true, 286 + dictDefaultMessage: $dropzone.data('default-message'), 287 + dictInvalidFileType: $dropzone.data('invalid-input-type'), 288 + dictFileTooBig: $dropzone.data('file-too-big'), 289 + dictRemoveFile: $dropzone.data('remove-file'), 290 + timeout: 0, 291 + thumbnailMethod: 'contain', 292 + thumbnailWidth: 480, 293 + thumbnailHeight: 480, 294 + init() { 295 + this.on('success', (file, data) => { 296 + fileUuidDict[file.uuid] = {submitted: false}; 297 + const input = $(`<input id="${data.uuid}" name="files" type="hidden">`).val(data.uuid); 298 + $dropzone.find('.files').append(input); 299 + }); 300 + this.on('removedfile', (file) => { 301 + $(`#${file.uuid}`).remove(); 302 + if ($dropzone.data('remove-url') && !fileUuidDict[file.uuid].submitted) { 303 + $.post($dropzone.data('remove-url'), { 304 + file: file.uuid, 305 + _csrf: csrfToken, 306 + }); 307 + } 308 + }); 309 + this.on('submit', () => { 310 + $.each(fileUuidDict, (fileUuid) => { 311 + fileUuidDict[fileUuid].submitted = true; 312 + }); 313 + }); 314 + this.on('reload', () => { 315 + $.getJSON($editContentZone.data('attachment-url'), (data) => { 316 + dz.removeAllFiles(true); 317 + $dropzone.find('.files').empty(); 318 + $.each(data, function () { 319 + const imgSrc = `${$dropzone.data('link-url')}/${this.uuid}`; 320 + dz.emit('addedfile', this); 321 + dz.emit('thumbnail', this, imgSrc); 322 + dz.emit('complete', this); 323 + dz.files.push(this); 324 + fileUuidDict[this.uuid] = {submitted: true}; 325 + $dropzone.find(`img[src='${imgSrc}']`).css('max-width', '100%'); 326 + const input = $(`<input id="${this.uuid}" name="files" type="hidden">`).val(this.uuid); 327 + $dropzone.find('.files').append(input); 328 + }); 329 + }); 330 + }); 331 + }, 332 + }); 333 + dz.emit('reload'); 334 + } 335 + // Give new write/preview data-tab name to distinguish from others 336 + const $editContentForm = $editContentZone.find('.ui.comment.form'); 337 + const $tabMenu = $editContentForm.find('.tabular.menu'); 338 + $tabMenu.attr('data-write', $editContentZone.data('write')); 339 + $tabMenu.attr('data-preview', $editContentZone.data('preview')); 340 + $tabMenu.find('.write.item').attr('data-tab', $editContentZone.data('write')); 341 + $tabMenu.find('.preview.item').attr('data-tab', $editContentZone.data('preview')); 342 + $editContentForm.find('.write').attr('data-tab', $editContentZone.data('write')); 343 + $editContentForm.find('.preview').attr('data-tab', $editContentZone.data('preview')); 344 + $simplemde = createCommentSimpleMDE($textarea); 345 + 346 + initCompMarkupContentPreviewTab($editContentForm); 347 + if ($dropzone.length === 1) { 348 + initSimpleMDEImagePaste($simplemde, $dropzone[0], $dropzone.find('.files')); 349 + } 350 + 351 + $editContentZone.find('.cancel.button').on('click', () => { 352 + $renderContent.show(); 353 + $editContentZone.hide(); 354 + if (dz) { 355 + dz.emit('reload'); 356 + } 357 + }); 358 + $editContentZone.find('.save.button').on('click', () => { 359 + $renderContent.show(); 360 + $editContentZone.hide(); 361 + const $attachments = $dropzone.find('.files').find('[name=files]').map(function () { 362 + return $(this).val(); 363 + }).get(); 364 + $.post($editContentZone.data('update-url'), { 365 + _csrf: csrfToken, 366 + content: $textarea.val(), 367 + context: $editContentZone.data('context'), 368 + files: $attachments, 369 + }, (data) => { 370 + if (data.length === 0 || data.content.length === 0) { 371 + $renderContent.html($('#no-content').html()); 372 + $rawContent.text(''); 373 + } else { 374 + $renderContent.html(data.content); 375 + $rawContent.text($textarea.val()); 376 + } 377 + const $content = $segment; 378 + if (!$content.find('.dropzone-attachments').length) { 379 + if (data.attachments !== '') { 380 + $content.append(`<div class="dropzone-attachments"></div>`); 381 + $content.find('.dropzone-attachments').replaceWith(data.attachments); 382 + } 383 + } else if (data.attachments === '') { 384 + $content.find('.dropzone-attachments').remove(); 385 + } else { 386 + $content.find('.dropzone-attachments').replaceWith(data.attachments); 387 + } 388 + if (dz) { 389 + dz.emit('submit'); 390 + dz.emit('reload'); 391 + } 392 + initMarkupContent(); 393 + initCommentContent(); 394 + }); 395 + }); 396 + } else { 397 + $textarea = $segment.find('textarea'); 398 + $simplemde = $textarea.data('simplemde'); 399 + } 400 + 401 + // Show write/preview tab and copy raw content as needed 402 + $editContentZone.show(); 403 + $renderContent.hide(); 404 + if ($textarea.val().length === 0) { 405 + $textarea.val($rawContent.text()); 406 + $simplemde.value($rawContent.text()); 407 + } 408 + requestAnimationFrame(() => { 409 + $textarea.focus(); 410 + $simplemde.codemirror.focus(); 411 + }); 412 + } 413 + 262 414 export function initRepository() { 263 415 if ($('.repository').length === 0) { 264 416 return; ··· 333 485 }); 334 486 } 335 487 488 + // Compare or pull request 489 + const $repoDiff = $('.repository.diff'); 490 + if ($repoDiff.length) { 491 + initRepoCommonBranchOrTagDropdown('.choose.branch .dropdown'); 492 + initRepoCommonFilterSearchDropdown('.choose.branch .dropdown'); 493 + } 494 + 495 + initRepoClone(); 496 + initRepoCommonLanguageStats(); 497 + initRepoSettingBranches(); 498 + 336 499 // Issues 337 500 if ($('.repository.view.issue').length > 0) { 501 + initRepoIssueCommentEdit(); 502 + 338 503 initRepoIssueBranchSelect(); 339 504 initRepoIssueTitleEdit(); 340 505 initRepoIssueWipToggle(); 341 506 initRepoIssueComments(); 342 507 343 - // Issue/PR Context Menus 344 - $('.context-dropdown').dropdown({ 345 - action: 'hide', 346 - }); 347 - 348 508 initRepoDiffConversationNav(); 349 - initRepoIssueQuoteReply(); 350 509 initRepoIssueReferenceIssue(); 351 510 352 - // Edit issue or comment content 353 - $(document).on('click', '.edit-content', async function (event) { 354 - event.preventDefault(); 355 - $(this).closest('.dropdown').find('.menu').toggle('visible'); 356 - const $segment = $(this).closest('.header').next(); 357 - const $editContentZone = $segment.find('.edit-content-zone'); 358 - const $renderContent = $segment.find('.render-content'); 359 - const $rawContent = $segment.find('.raw-content'); 360 - let $textarea; 361 - let $simplemde; 362 - 363 - // Setup new form 364 - if ($editContentZone.html().length === 0) { 365 - $editContentZone.html($('#edit-content-form').html()); 366 - $textarea = $editContentZone.find('textarea'); 367 - await attachTribute($textarea.get(), {mentions: true, emoji: true}); 368 - 369 - let dz; 370 - const $dropzone = $editContentZone.find('.dropzone'); 371 - if ($dropzone.length === 1) { 372 - $dropzone.data('saved', false); 373 - 374 - const fileUuidDict = {}; 375 - dz = await createDropzone($dropzone[0], { 376 - url: $dropzone.data('upload-url'), 377 - headers: {'X-Csrf-Token': csrfToken}, 378 - maxFiles: $dropzone.data('max-file'), 379 - maxFilesize: $dropzone.data('max-size'), 380 - acceptedFiles: (['*/*', ''].includes($dropzone.data('accepts'))) ? null : $dropzone.data('accepts'), 381 - addRemoveLinks: true, 382 - dictDefaultMessage: $dropzone.data('default-message'), 383 - dictInvalidFileType: $dropzone.data('invalid-input-type'), 384 - dictFileTooBig: $dropzone.data('file-too-big'), 385 - dictRemoveFile: $dropzone.data('remove-file'), 386 - timeout: 0, 387 - thumbnailMethod: 'contain', 388 - thumbnailWidth: 480, 389 - thumbnailHeight: 480, 390 - init() { 391 - this.on('success', (file, data) => { 392 - fileUuidDict[file.uuid] = { 393 - submitted: false, 394 - }; 395 - const input = $(`<input id="${data.uuid}" name="files" type="hidden">`).val(data.uuid); 396 - $dropzone.find('.files').append(input); 397 - }); 398 - this.on('removedfile', (file) => { 399 - $(`#${file.uuid}`).remove(); 400 - if ($dropzone.data('remove-url') && !fileUuidDict[file.uuid].submitted) { 401 - $.post($dropzone.data('remove-url'), { 402 - file: file.uuid, 403 - _csrf: csrfToken, 404 - }); 405 - } 406 - }); 407 - this.on('submit', () => { 408 - $.each(fileUuidDict, (fileUuid) => { 409 - fileUuidDict[fileUuid].submitted = true; 410 - }); 411 - }); 412 - this.on('reload', () => { 413 - $.getJSON($editContentZone.data('attachment-url'), (data) => { 414 - dz.removeAllFiles(true); 415 - $dropzone.find('.files').empty(); 416 - $.each(data, function () { 417 - const imgSrc = `${$dropzone.data('link-url')}/${this.uuid}`; 418 - dz.emit('addedfile', this); 419 - dz.emit('thumbnail', this, imgSrc); 420 - dz.emit('complete', this); 421 - dz.files.push(this); 422 - fileUuidDict[this.uuid] = { 423 - submitted: true, 424 - }; 425 - $dropzone.find(`img[src='${imgSrc}']`).css('max-width', '100%'); 426 - const input = $(`<input id="${this.uuid}" name="files" type="hidden">`).val(this.uuid); 427 - $dropzone.find('.files').append(input); 428 - }); 429 - }); 430 - }); 431 - }, 432 - }); 433 - dz.emit('reload'); 434 - } 435 - // Give new write/preview data-tab name to distinguish from others 436 - const $editContentForm = $editContentZone.find('.ui.comment.form'); 437 - const $tabMenu = $editContentForm.find('.tabular.menu'); 438 - $tabMenu.attr('data-write', $editContentZone.data('write')); 439 - $tabMenu.attr('data-preview', $editContentZone.data('preview')); 440 - $tabMenu.find('.write.item').attr('data-tab', $editContentZone.data('write')); 441 - $tabMenu.find('.preview.item').attr('data-tab', $editContentZone.data('preview')); 442 - $editContentForm.find('.write').attr('data-tab', $editContentZone.data('write')); 443 - $editContentForm.find('.preview').attr('data-tab', $editContentZone.data('preview')); 444 - $simplemde = createCommentSimpleMDE($textarea); 445 - commentMDEditors[$editContentZone.data('write')] = $simplemde; 446 - initCompMarkupContentPreviewTab($editContentForm); 447 - if ($dropzone.length === 1) { 448 - initSimpleMDEImagePaste($simplemde, $dropzone[0], $dropzone.find('.files')); 449 - } 450 - 451 - $editContentZone.find('.cancel.button').on('click', () => { 452 - $renderContent.show(); 453 - $editContentZone.hide(); 454 - if (dz) { 455 - dz.emit('reload'); 456 - } 457 - }); 458 - $editContentZone.find('.save.button').on('click', () => { 459 - $renderContent.show(); 460 - $editContentZone.hide(); 461 - const $attachments = $dropzone.find('.files').find('[name=files]').map(function () { 462 - return $(this).val(); 463 - }).get(); 464 - $.post($editContentZone.data('update-url'), { 465 - _csrf: csrfToken, 466 - content: $textarea.val(), 467 - context: $editContentZone.data('context'), 468 - files: $attachments, 469 - }, (data) => { 470 - if (data.length === 0 || data.content.length === 0) { 471 - $renderContent.html($('#no-content').html()); 472 - $rawContent.text(''); 473 - } else { 474 - $renderContent.html(data.content); 475 - $rawContent.text($textarea.val()); 476 - } 477 - const $content = $segment; 478 - if (!$content.find('.dropzone-attachments').length) { 479 - if (data.attachments !== '') { 480 - $content.append(` 481 - <div class="dropzone-attachments"> 482 - </div> 483 - `); 484 - $content.find('.dropzone-attachments').replaceWith(data.attachments); 485 - } 486 - } else if (data.attachments === '') { 487 - $content.find('.dropzone-attachments').remove(); 488 - } else { 489 - $content.find('.dropzone-attachments').replaceWith(data.attachments); 490 - } 491 - if (dz) { 492 - dz.emit('submit'); 493 - dz.emit('reload'); 494 - } 495 - initMarkupContent(); 496 - initCommentContent(); 497 - }); 498 - }); 499 - } else { 500 - $textarea = $segment.find('textarea'); 501 - $simplemde = commentMDEditors[$editContentZone.data('write')]; 502 - } 503 - 504 - // Show write/preview tab and copy raw content as needed 505 - $editContentZone.show(); 506 - $renderContent.hide(); 507 - if ($textarea.val().length === 0) { 508 - $textarea.val($rawContent.text()); 509 - $simplemde.value($rawContent.text()); 510 - } 511 - requestAnimationFrame(() => { 512 - $textarea.focus(); 513 - $simplemde.codemirror.focus(); 514 - }); 515 - }); 516 511 517 512 initRepoIssueCommentDelete(); 518 513 initRepoIssueDependencyDelete(); ··· 523 518 initCompReactionSelector(); 524 519 } 525 520 526 - initRepoClone(); 527 - 528 - // Compare or pull request 529 - const $repoDiff = $('.repository.diff'); 530 - if ($repoDiff.length) { 531 - initRepoCommonBranchOrTagDropdown('.choose.branch .dropdown'); 532 - initRepoCommonFilterSearchDropdown('.choose.branch .dropdown'); 533 - } 534 - 535 521 // Pull request 536 522 const $repoComparePull = $('.repository.compare.pull'); 537 523 if ($repoComparePull.length > 0) { 538 524 // show pull request form 539 525 $repoComparePull.find('button.show-form').on('click', function (e) { 540 526 e.preventDefault(); 541 - $repoComparePull.find('.pullrequest-form').show(); 542 - autoSimpleMDE.codemirror.refresh(); 543 527 $(this).parent().hide(); 528 + 529 + const $form = $repoComparePull.find('.pullrequest-form'); 530 + const $simplemde = $form.find('textarea.edit_area').data('simplemde'); 531 + $form.show(); 532 + $simplemde.codemirror.refresh(); 544 533 }); 545 534 } 546 - 547 - initRepoSettingBranches(); 548 - initRepoCommonLanguageStats(); 549 535 } 550 536 551 - function initRepoIssueQuoteReply() { 537 + function initRepoIssueCommentEdit() { 538 + // Issue/PR Context Menus 539 + $('.comment-header-right .context-dropdown').dropdown({action: 'hide'}); 540 + 541 + // Edit issue or comment content 542 + $(document).on('click', '.edit-content', onEditContent); 543 + 552 544 // Quote reply 553 545 $(document).on('click', '.quote-reply', function (event) { 554 546 $(this).closest('.dropdown').find('.menu').toggle('visible'); 555 547 const target = $(this).data('target'); 556 548 const quote = $(`#comment-${target}`).text().replace(/\n/g, '\n> '); 557 549 const content = `> ${quote}\n\n`; 558 - let $simplemde = autoSimpleMDE; 550 + let $simplemde; 559 551 if ($(this).hasClass('quote-reply-diff')) { 560 552 const $parent = $(this).closest('.comment-code-cloud'); 561 553 $parent.find('button.comment-form-reply').trigger('click'); 562 554 $simplemde = $parent.find('[name="content"]').data('simplemde'); 555 + } else { 556 + // for normal issue/comment page 557 + $simplemde = $('#comment-form .edit_area').data('simplemde'); 563 558 } 564 - if ($simplemde !== null) { 559 + if ($simplemde) { 565 560 if ($simplemde.value() !== '') { 566 561 $simplemde.value(`${$simplemde.value()}\n\n${content}`); 567 562 } else { 568 563 $simplemde.value(`${content}`); 569 564 } 565 + requestAnimationFrame(() => { 566 + $simplemde.codemirror.focus(); 567 + $simplemde.codemirror.setCursor($simplemde.codemirror.lineCount(), 0); 568 + }); 570 569 } 571 - requestAnimationFrame(() => { 572 - $simplemde.codemirror.focus(); 573 - $simplemde.codemirror.setCursor($simplemde.codemirror.lineCount(), 0); 574 - }); 575 570 event.preventDefault(); 576 571 }); 577 572 }
+4 -2
web_src/js/features/repo-projects.js
··· 1 1 const {csrfToken} = window.config; 2 2 3 3 async function initRepoProjectSortable() { 4 + const els = document.getElementsByClassName('board'); 5 + if (!els.length) return; 6 + 4 7 const {Sortable} = await import(/* webpackChunkName: "sortable" */'sortablejs'); 5 8 const boardColumns = document.getElementsByClassName('board-column'); 6 - 7 9 new Sortable( 8 - document.getElementsByClassName('board')[0], 10 + els[0], 9 11 { 10 12 group: 'board-column', 11 13 draggable: '.board-column',