123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613 |
- import $ from 'jquery';
- import {createCommentEasyMDE, getAttachedEasyMDE} from './comp/EasyMDE.js';
- import {initCompMarkupContentPreviewTab} from './comp/MarkupContentPreview.js';
- import {initEasyMDEImagePaste} from './comp/ImagePaste.js';
- import {
- initRepoIssueBranchSelect, initRepoIssueCodeCommentCancel, initRepoIssueCommentDelete,
- initRepoIssueComments, initRepoIssueDependencyDelete, initRepoIssueReferenceIssue,
- initRepoIssueStatusButton, initRepoIssueTitleEdit, initRepoIssueWipToggle,
- initRepoPullRequestUpdate, updateIssuesMeta,
- } from './repo-issue.js';
- import {initUnicodeEscapeButton} from './repo-unicode-escape.js';
- import {svg} from '../svg.js';
- import {htmlEscape} from 'escape-goat';
- import {initRepoBranchTagDropdown} from '../components/RepoBranchTagDropdown.js';
- import {
- initRepoCloneLink, initRepoCommonBranchOrTagDropdown, initRepoCommonFilterSearchDropdown,
- initRepoCommonLanguageStats,
- } from './repo-common.js';
- import {initCitationFileCopyContent} from './citation.js';
- import {initCompLabelEdit} from './comp/LabelEdit.js';
- import {initRepoDiffConversationNav} from './repo-diff.js';
- import {attachTribute} from './tribute.js';
- import {createDropzone} from './dropzone.js';
- import {initCommentContent, initMarkupContent} from '../markup/content.js';
- import {initCompReactionSelector} from './comp/ReactionSelector.js';
- import {initRepoSettingBranches} from './repo-settings.js';
- import {initRepoPullRequestMergeForm} from './repo-issue-pr-form.js';
- import {hideElem, showElem} from '../utils/dom.js';
-
- const {csrfToken} = window.config;
-
- export function initRepoCommentForm() {
- const $commentForm = $('.comment.form');
- if ($commentForm.length === 0) {
- return;
- }
-
- function initBranchSelector() {
- const $selectBranch = $('.ui.select-branch');
- const $branchMenu = $selectBranch.find('.reference-list-menu');
- const $isNewIssue = $branchMenu.hasClass('new-issue');
- $branchMenu.find('.item:not(.no-select)').click(function () {
- const selectedValue = $(this).data('id');
- const editMode = $('#editing_mode').val();
- $($(this).data('id-selector')).val(selectedValue);
- if ($isNewIssue) {
- $selectBranch.find('.ui .branch-name').text($(this).data('name'));
- return;
- }
-
- if (editMode === 'true') {
- const form = $('#update_issueref_form');
- $.post(form.attr('action'), {_csrf: csrfToken, ref: selectedValue}, () => window.location.reload());
- } else if (editMode === '') {
- $selectBranch.find('.ui .branch-name').text(selectedValue);
- }
- });
- $selectBranch.find('.reference.column').on('click', function () {
- hideElem($selectBranch.find('.scrolling.reference-list-menu'));
- $selectBranch.find('.reference .text').removeClass('black');
- showElem($($(this).data('target')));
- $(this).find('.text').addClass('black');
- return false;
- });
- }
-
- (async () => {
- for (const textarea of $commentForm.find('textarea:not(.review-textarea, .no-easymde)')) {
- // Don't initialize EasyMDE for the dormant #edit-content-form
- if (textarea.closest('#edit-content-form')) {
- continue;
- }
- const easyMDE = await createCommentEasyMDE(textarea);
- initEasyMDEImagePaste(easyMDE, $commentForm.find('.dropzone'));
- }
- })();
-
- initBranchSelector();
- initCompMarkupContentPreviewTab($commentForm);
-
- // List submits
- function initListSubmits(selector, outerSelector) {
- const $list = $(`.ui.${outerSelector}.list`);
- const $noSelect = $list.find('.no-select');
- const $listMenu = $(`.${selector} .menu`);
- let hasUpdateAction = $listMenu.data('action') === 'update';
- const items = {};
-
- $(`.${selector}`).dropdown('setting', 'onHide', () => {
- hasUpdateAction = $listMenu.data('action') === 'update'; // Update the var
- if (hasUpdateAction) {
- // TODO: Add batch functionality and make this 1 network request.
- (async function() {
- for (const [elementId, item] of Object.entries(items)) {
- await updateIssuesMeta(
- item['update-url'],
- item.action,
- item['issue-id'],
- elementId,
- );
- }
- window.location.reload();
- })();
- }
- });
-
- $listMenu.find('.item:not(.no-select)').on('click', function (e) {
- e.preventDefault();
- if ($(this).hasClass('ban-change')) {
- return false;
- }
-
- hasUpdateAction = $listMenu.data('action') === 'update'; // Update the var
-
- const clickedItem = $(this);
- const scope = $(this).attr('data-scope');
- const canRemoveScope = e.altKey;
-
- $(this).parent().find('.item').each(function () {
- if (scope) {
- // Enable only clicked item for scoped labels
- if ($(this).attr('data-scope') !== scope) {
- return true;
- }
- if ($(this).is(clickedItem)) {
- if (!canRemoveScope && $(this).hasClass('checked')) {
- return true;
- }
- } else if (!$(this).hasClass('checked')) {
- return true;
- }
- } else if (!$(this).is(clickedItem)) {
- // Toggle for other labels
- return true;
- }
-
- if ($(this).hasClass('checked')) {
- $(this).removeClass('checked');
- $(this).find('.octicon-check').addClass('invisible');
- if (hasUpdateAction) {
- if (!($(this).data('id') in items)) {
- items[$(this).data('id')] = {
- 'update-url': $listMenu.data('update-url'),
- action: 'detach',
- 'issue-id': $listMenu.data('issue-id'),
- };
- } else {
- delete items[$(this).data('id')];
- }
- }
- } else {
- $(this).addClass('checked');
- $(this).find('.octicon-check').removeClass('invisible');
- if (hasUpdateAction) {
- if (!($(this).data('id') in items)) {
- items[$(this).data('id')] = {
- 'update-url': $listMenu.data('update-url'),
- action: 'attach',
- 'issue-id': $listMenu.data('issue-id'),
- };
- } else {
- delete items[$(this).data('id')];
- }
- }
- }
- });
-
- // TODO: Which thing should be done for choosing review requests
- // to make chosen items be shown on time here?
- if (selector === 'select-reviewers-modify' || selector === 'select-assignees-modify') {
- return false;
- }
-
- const listIds = [];
- $(this).parent().find('.item').each(function () {
- if ($(this).hasClass('checked')) {
- listIds.push($(this).data('id'));
- $($(this).data('id-selector')).removeClass('gt-hidden');
- } else {
- $($(this).data('id-selector')).addClass('gt-hidden');
- }
- });
- if (listIds.length === 0) {
- $noSelect.removeClass('gt-hidden');
- } else {
- $noSelect.addClass('gt-hidden');
- }
- $($(this).parent().data('id')).val(listIds.join(','));
- return false;
- });
- $listMenu.find('.no-select.item').on('click', function (e) {
- e.preventDefault();
- if (hasUpdateAction) {
- updateIssuesMeta(
- $listMenu.data('update-url'),
- 'clear',
- $listMenu.data('issue-id'),
- '',
- ).then(() => window.location.reload());
- }
-
- $(this).parent().find('.item').each(function () {
- $(this).removeClass('checked');
- $(this).find('.octicon').addClass('invisible');
- });
-
- if (selector === 'select-reviewers-modify' || selector === 'select-assignees-modify') {
- return false;
- }
-
- $list.find('.item').each(function () {
- $(this).addClass('gt-hidden');
- });
- $noSelect.removeClass('gt-hidden');
- $($(this).parent().data('id')).val('');
- });
- }
-
- // Init labels and assignees
- initListSubmits('select-label', 'labels');
- initListSubmits('select-assignees', 'assignees');
- initListSubmits('select-assignees-modify', 'assignees');
- initListSubmits('select-reviewers-modify', 'assignees');
-
- function selectItem(select_id, input_id) {
- const $menu = $(`${select_id} .menu`);
- const $list = $(`.ui${select_id}.list`);
- const hasUpdateAction = $menu.data('action') === 'update';
-
- $menu.find('.item:not(.no-select)').on('click', function () {
- $(this).parent().find('.item').each(function () {
- $(this).removeClass('selected active');
- });
-
- $(this).addClass('selected active');
- if (hasUpdateAction) {
- updateIssuesMeta(
- $menu.data('update-url'),
- '',
- $menu.data('issue-id'),
- $(this).data('id'),
- ).then(() => window.location.reload());
- }
-
- let icon = '';
- if (input_id === '#milestone_id') {
- icon = svg('octicon-milestone', 18, 'gt-mr-3');
- } else if (input_id === '#project_id') {
- icon = svg('octicon-project', 18, 'gt-mr-3');
- } else if (input_id === '#assignee_id') {
- icon = `<img class="ui avatar image gt-mr-3" src=${$(this).data('avatar')}>`;
- }
-
- $list.find('.selected').html(`
- <a class="item muted sidebar-item-link" href=${$(this).data('href')}>
- ${icon}
- ${htmlEscape($(this).text())}
- </a>
- `);
-
- $(`.ui${select_id}.list .no-select`).addClass('gt-hidden');
- $(input_id).val($(this).data('id'));
- });
- $menu.find('.no-select.item').on('click', function () {
- $(this).parent().find('.item:not(.no-select)').each(function () {
- $(this).removeClass('selected active');
- });
-
- if (hasUpdateAction) {
- updateIssuesMeta(
- $menu.data('update-url'),
- '',
- $menu.data('issue-id'),
- $(this).data('id'),
- ).then(() => window.location.reload());
- }
-
- $list.find('.selected').html('');
- $list.find('.no-select').removeClass('gt-hidden');
- $(input_id).val('');
- });
- }
-
- // Milestone, Assignee, Project
- selectItem('.select-project', '#project_id');
- selectItem('.select-milestone', '#milestone_id');
- selectItem('.select-assignee', '#assignee_id');
- }
-
-
- async function onEditContent(event) {
- event.preventDefault();
-
- $(this).closest('.dropdown').find('.menu').toggle('visible'); // eslint-disable-line
- 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 easyMDE;
-
- // 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) => {
- file.uuid = data.uuid;
- 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'));
- easyMDE = await createCommentEasyMDE($textarea);
-
- initCompMarkupContentPreviewTab($editContentForm);
- initEasyMDEImagePaste(easyMDE, $dropzone);
-
- const $saveButton = $editContentZone.find('.save.button');
- $textarea.on('ce-quick-submit', () => {
- $saveButton.trigger('click');
- });
-
- $editContentZone.find('.cancel.button').on('click', () => {
- showElem($renderContent);
- hideElem($editContentZone);
- if (dz) {
- dz.emit('reload');
- }
- });
-
- $saveButton.on('click', () => {
- showElem($renderContent);
- hideElem($editContentZone);
- 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 { // use existing form
- $textarea = $segment.find('textarea');
- easyMDE = getAttachedEasyMDE($textarea);
- }
-
- // Show write/preview tab and copy raw content as needed
- showElem($editContentZone);
- hideElem($renderContent);
- if ($textarea.val().length === 0) {
- $textarea.val($rawContent.text());
- easyMDE.value($rawContent.text());
- }
- requestAnimationFrame(() => {
- $textarea.focus();
- easyMDE.codemirror.focus();
- });
- }
-
- export function initRepository() {
- if ($('.repository').length === 0) {
- return;
- }
-
-
- // File list and commits
- if ($('.repository.file.list').length > 0 || $('.branch-dropdown').length > 0 ||
- $('.repository.commits').length > 0 || $('.repository.release').length > 0) {
- initRepoBranchTagDropdown('.choose.reference .dropdown');
- }
-
- // Wiki
- if ($('.repository.wiki.view').length > 0) {
- initRepoCommonFilterSearchDropdown('.choose.page .dropdown');
- }
-
- // Options
- if ($('.repository.settings.options').length > 0) {
- // Enable or select internal/external wiki system and issue tracker.
- $('.enable-system').on('change', function () {
- if (this.checked) {
- $($(this).data('target')).removeClass('disabled');
- if (!$(this).data('context')) $($(this).data('context')).addClass('disabled');
- } else {
- $($(this).data('target')).addClass('disabled');
- if (!$(this).data('context')) $($(this).data('context')).removeClass('disabled');
- }
- });
- $('.enable-system-radio').on('change', function () {
- if (this.value === 'false') {
- $($(this).data('target')).addClass('disabled');
- if ($(this).data('context') !== undefined) $($(this).data('context')).removeClass('disabled');
- } else if (this.value === 'true') {
- $($(this).data('target')).removeClass('disabled');
- if ($(this).data('context') !== undefined) $($(this).data('context')).addClass('disabled');
- }
- });
- const $trackerIssueStyleRadios = $('.js-tracker-issue-style');
- $trackerIssueStyleRadios.on('change input', () => {
- const checkedVal = $trackerIssueStyleRadios.filter(':checked').val();
- $('#tracker-issue-style-regex-box').toggleClass('disabled', checkedVal !== 'regexp');
- });
- }
-
- // Labels
- initCompLabelEdit('.repository.labels');
-
- // Milestones
- if ($('.repository.new.milestone').length > 0) {
- $('#clear-date').on('click', () => {
- $('#deadline').val('');
- return false;
- });
- }
-
- // Repo Creation
- if ($('.repository.new.repo').length > 0) {
- $('input[name="gitignores"], input[name="license"]').on('change', () => {
- const gitignores = $('input[name="gitignores"]').val();
- const license = $('input[name="license"]').val();
- if (gitignores || license) {
- $('input[name="auto_init"]').prop('checked', true);
- }
- });
- }
-
- // Compare or pull request
- const $repoDiff = $('.repository.diff');
- if ($repoDiff.length) {
- initRepoCommonBranchOrTagDropdown('.choose.branch .dropdown');
- initRepoCommonFilterSearchDropdown('.choose.branch .dropdown');
- }
-
- initRepoCloneLink();
- initCitationFileCopyContent();
- initRepoCommonLanguageStats();
- initRepoSettingBranches();
-
- // Issues
- if ($('.repository.view.issue').length > 0) {
- initRepoIssueCommentEdit();
-
- initRepoIssueBranchSelect();
- initRepoIssueTitleEdit();
- initRepoIssueWipToggle();
- initRepoIssueComments();
-
- initRepoDiffConversationNav();
- initRepoIssueReferenceIssue();
-
-
- initRepoIssueCommentDelete();
- initRepoIssueDependencyDelete();
- initRepoIssueCodeCommentCancel();
- initRepoIssueStatusButton();
- initRepoPullRequestUpdate();
- initCompReactionSelector();
-
- initRepoPullRequestMergeForm();
- }
-
- // Pull request
- const $repoComparePull = $('.repository.compare.pull');
- if ($repoComparePull.length > 0) {
- // show pull request form
- $repoComparePull.find('button.show-form').on('click', function (e) {
- e.preventDefault();
- hideElem($(this).parent());
-
- const $form = $repoComparePull.find('.pullrequest-form');
- showElem($form);
- $form.find('textarea.edit_area').each(function() {
- const easyMDE = getAttachedEasyMDE($(this));
- if (easyMDE) {
- easyMDE.codemirror.refresh();
- }
- });
- });
- }
-
- initUnicodeEscapeButton();
- }
-
- 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
- $(document).on('click', '.quote-reply', function (event) {
- $(this).closest('.dropdown').find('.menu').toggle('visible'); // eslint-disable-line
- const target = $(this).data('target');
- const quote = $(`#${target}`).text().replace(/\n/g, '\n> ');
- const content = `> ${quote}\n\n`;
- let easyMDE;
- if ($(this).hasClass('quote-reply-diff')) {
- const $parent = $(this).closest('.comment-code-cloud');
- $parent.find('button.comment-form-reply').trigger('click');
- easyMDE = getAttachedEasyMDE($parent.find('[name="content"]'));
- } else {
- // for normal issue/comment page
- easyMDE = getAttachedEasyMDE($('#comment-form .edit_area'));
- }
- if (easyMDE) {
- if (easyMDE.value() !== '') {
- easyMDE.value(`${easyMDE.value()}\n\n${content}`);
- } else {
- easyMDE.value(`${content}`);
- }
- requestAnimationFrame(() => {
- easyMDE.codemirror.focus();
- easyMDE.codemirror.setCursor(easyMDE.codemirror.lineCount(), 0);
- });
- }
- event.preventDefault();
- });
- }
|