aboutsummaryrefslogtreecommitdiffstats
path: root/web_src/js/features/repo-legacy.js
diff options
context:
space:
mode:
Diffstat (limited to 'web_src/js/features/repo-legacy.js')
-rw-r--r--web_src/js/features/repo-legacy.js574
1 files changed, 574 insertions, 0 deletions
diff --git a/web_src/js/features/repo-legacy.js b/web_src/js/features/repo-legacy.js
new file mode 100644
index 0000000000..a1c405d719
--- /dev/null
+++ b/web_src/js/features/repo-legacy.js
@@ -0,0 +1,574 @@
+import {createCommentSimpleMDE} from './comp/CommentSimpleMDE.js';
+import {initCompMarkupContentPreviewTab} from './comp/MarkupContentPreview.js';
+import {initCompImagePaste, initSimpleMDEImagePaste} from './comp/ImagePaste.js';
+import {
+ initRepoIssueBranchSelect, initRepoIssueCodeCommentCancel,
+ initRepoIssueCommentDelete,
+ initRepoIssueComments, initRepoIssueDependencyDelete,
+ initRepoIssueReferenceIssue, initRepoIssueStatusButton,
+ initRepoIssueTitleEdit,
+ initRepoIssueWipToggle, initRepoPullRequestMerge, initRepoPullRequestUpdate,
+ updateIssuesMeta,
+} from './repo-issue.js';
+import {svg} from '../svg.js';
+import {htmlEscape} from 'escape-goat';
+import {initRepoBranchTagDropdown} from '../components/RepoBranchTagDropdown.js';
+import {
+ initRepoClone,
+ initRepoCommonBranchOrTagDropdown,
+ initRepoCommonFilterSearchDropdown,
+ initRepoCommonLanguageStats,
+} from './repo-common.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';
+
+const {csrf} = 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() {
+ if ($('.comment.form').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: csrf, ref: selectedValue}, () => window.location.reload());
+ } else if (editMode === '') {
+ $selectBranch.find('.ui .branch-name').text(selectedValue);
+ }
+ });
+ $selectBranch.find('.reference.column').on('click', function () {
+ $selectBranch.find('.scrolling.reference-list-menu').css('display', 'none');
+ $selectBranch.find('.reference .text').removeClass('black');
+ $($(this).data('target')).css('display', 'block');
+ $(this).find('.text').addClass('black');
+ return false;
+ });
+ }
+
+ autoSimpleMDE = createCommentSimpleMDE($('.comment.form textarea:not(.review-textarea)'));
+ initBranchSelector();
+ initCompMarkupContentPreviewTab($('.comment.form'));
+ initCompImagePaste($('.comment.form'));
+
+ // Listsubmit
+ 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) {
+ const promises = [];
+ Object.keys(items).forEach((elementId) => {
+ const item = items[elementId];
+ const promise = updateIssuesMeta(
+ item['update-url'],
+ item.action,
+ item['issue-id'],
+ elementId,
+ );
+ promises.push(promise);
+ });
+ Promise.all(promises).then(() => 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
+ 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('hide');
+ } else {
+ $($(this).data('id-selector')).addClass('hide');
+ }
+ });
+ if (listIds.length === 0) {
+ $noSelect.removeClass('hide');
+ } else {
+ $noSelect.addClass('hide');
+ }
+ $($(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('hide');
+ });
+ $noSelect.removeClass('hide');
+ $($(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, 'mr-3');
+ } else if (input_id === '#project_id') {
+ icon = svg('octicon-project', 18, 'mr-3');
+ } else if (input_id === '#assignee_id') {
+ icon = `<img class="ui avatar image 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('hide');
+ $(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('hide');
+ $(input_id).val('');
+ });
+ }
+
+ // Milestone, Assignee, Project
+ selectItem('.select-project', '#project_id');
+ selectItem('.select-milestone', '#milestone_id');
+ selectItem('.select-assignee', '#assignee_id');
+}
+
+
+export async function initRepository() {
+ if ($('.repository').length === 0) {
+ return;
+ }
+
+
+ // Commit statuses
+ $('.commit-statuses-trigger').each(function () {
+ $(this)
+ .popup({
+ on: 'click',
+ position: ($('.repository.file.list').length > 0 ? 'right center' : 'left center'),
+ });
+ });
+
+ // File list and commits
+ if ($('.repository.file.list').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 (typeof $(this).data('context') !== 'undefined') $($(this).data('context')).removeClass('disabled');
+ } else if (this.value === 'true') {
+ $($(this).data('target')).removeClass('disabled');
+ if (typeof $(this).data('context') !== 'undefined') $($(this).data('context')).addClass('disabled');
+ }
+ });
+ }
+
+ // 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);
+ }
+ });
+ }
+
+ // Issues
+ if ($('.repository.view.issue').length > 0) {
+ initRepoIssueBranchSelect();
+ initRepoIssueTitleEdit();
+ initRepoIssueWipToggle();
+ initRepoIssueComments();
+
+ // Issue/PR Context Menus
+ $('.context-dropdown').dropdown({
+ action: 'hide',
+ });
+
+ initRepoDiffConversationNav();
+ initRepoIssueQuoteReply();
+ initRepoIssueReferenceIssue();
+
+ // Edit issue or comment content
+ $(document).on('click', '.edit-content', async function (event) {
+ $(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');
+ 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': csrf},
+ 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: csrf,
+ });
+ }
+ });
+ 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: csrf,
+ 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 = 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();
+ });
+ event.preventDefault();
+ });
+
+ initRepoIssueCommentDelete();
+ initRepoIssueDependencyDelete();
+ initRepoIssueCodeCommentCancel();
+ initRepoIssueStatusButton();
+ initRepoPullRequestMerge();
+ initRepoPullRequestUpdate();
+ initCompReactionSelector();
+ }
+
+ initRepoClone();
+
+ // Compare or pull request
+ const $repoDiff = $('.repository.diff');
+ if ($repoDiff.length) {
+ initRepoCommonBranchOrTagDropdown('.choose.branch .dropdown');
+ initRepoCommonFilterSearchDropdown('.choose.branch .dropdown');
+ }
+
+ // 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();
+ $repoComparePull.find('.pullrequest-form').show();
+ autoSimpleMDE.codemirror.refresh();
+ $(this).parent().hide();
+ });
+ }
+
+ initRepoSettingBranches();
+ initRepoCommonLanguageStats();
+}
+
+function initRepoIssueQuoteReply() {
+ // Quote reply
+ $(document).on('click', '.quote-reply', function (event) {
+ $(this).closest('.dropdown').find('.menu').toggle('visible');
+ const target = $(this).data('target');
+ const quote = $(`#comment-${target}`).text().replace(/\n/g, '\n> ');
+ const content = `> ${quote}\n\n`;
+ let $simplemde = autoSimpleMDE;
+ if ($(this).hasClass('quote-reply-diff')) {
+ const $parent = $(this).closest('.comment-code-cloud');
+ $parent.find('button.comment-form-reply').trigger('click');
+ $simplemde = $parent.find('[name="content"]').data('simplemde');
+ }
+ if ($simplemde !== null) {
+ if ($simplemde.value() !== '') {
+ $simplemde.value(`${$simplemde.value()}\n\n${content}`);
+ } else {
+ $simplemde.value(`${content}`);
+ }
+ }
+ requestAnimationFrame(() => {
+ $simplemde.codemirror.focus();
+ $simplemde.codemirror.setCursor($simplemde.codemirror.lineCount(), 0);
+ });
+ event.preventDefault();
+ });
+}