Browse Source

Misc JS linting and naming tweaks (#10652)

- lowercase all js filenames except Vue components
- enable new lint rules, mostly focused on shorter code
- autofix new lint violations
- apply misc transformations indexOf -> includes and onevent-> addEventListener

Co-authored-by: Antoine GIRARD <sapk@users.noreply.github.com>
tags/v1.13.0-dev
silverwind 4 years ago
parent
commit
e03d627769
No account linked to committer's email address

+ 9
- 2
.eslintrc View File

- eslint:recommended - eslint:recommended


ignorePatterns: ignorePatterns:
- /web_src/js/vendor
- /web_src/js/vendor


parserOptions: parserOptions:
ecmaVersion: 2020 ecmaVersion: 2020


rules: rules:
arrow-body-style: [0] arrow-body-style: [0]
arrow-parens: [2, always]
camelcase: [0] camelcase: [0]
comma-dangle: [2, only-multiline] comma-dangle: [2, only-multiline]
consistent-return: [0] consistent-return: [0]
default-case: [0] default-case: [0]
func-names: [0] func-names: [0]
import/extensions: [0]
import/extensions: [2, always, {ignorePackages: true}]
import/prefer-default-export: [0] import/prefer-default-export: [0]
max-len: [0] max-len: [0]
multiline-comment-style: [2, separate-lines]
newline-per-chained-call: [0] newline-per-chained-call: [0]
no-alert: [0] no-alert: [0]
no-cond-assign: [2, except-parens] no-cond-assign: [2, except-parens]
no-console: [1, {allow: [info, warn, error]}] no-console: [1, {allow: [info, warn, error]}]
no-continue: [0] no-continue: [0]
no-eq-null: [2]
no-mixed-operators: [0] no-mixed-operators: [0]
no-multi-assign: [0] no-multi-assign: [0]
no-new: [0] no-new: [0]
no-unused-vars: [2, {args: all, argsIgnorePattern: ^_, varsIgnorePattern: ^_, ignoreRestSiblings: true}] no-unused-vars: [2, {args: all, argsIgnorePattern: ^_, varsIgnorePattern: ^_, ignoreRestSiblings: true}]
no-use-before-define: [0] no-use-before-define: [0]
no-var: [2] no-var: [2]
object-curly-spacing: [2, never]
one-var-declaration-per-line: [0] one-var-declaration-per-line: [0]
one-var: [0] one-var: [0]
operator-linebreak: [2, after]
prefer-const: [2, {destructuring: all}] prefer-const: [2, {destructuring: all}]
prefer-destructuring: [0] prefer-destructuring: [0]
quotes: [2, single, {avoidEscape: true, allowTemplateLiterals: true}]
radix: [2, as-needed] radix: [2, as-needed]
semi: [2, always, {omitLastInOneLineBlock: true}]

+ 1
- 1
web_src/js/features/clipboard.js View File

const els = document.querySelectorAll('.clipboard'); const els = document.querySelectorAll('.clipboard');
if (!els || !els.length) return; if (!els || !els.length) return;


const { default: ClipboardJS } = await import(/* webpackChunkName: "clipboard" */'clipboard');
const {default: ClipboardJS} = await import(/* webpackChunkName: "clipboard" */'clipboard');


const clipboard = new ClipboardJS(els); const clipboard = new ClipboardJS(els);
clipboard.on('success', (e) => { clipboard.on('success', (e) => {

web_src/js/features/contextPopup.js → web_src/js/features/contextpopup.js View File

import { svg } from '../utils.js';
import {svg} from '../utils.js';


const { AppSubUrl } = window.config;
const {AppSubUrl} = window.config;


export default function initContextPopups() { export default function initContextPopups() {
const refIssues = $('.ref-issue'); const refIssues = $('.ref-issue');


function issuePopup(owner, repo, index, $element) { function issuePopup(owner, repo, index, $element) {
$.get(`${AppSubUrl}/api/v1/repos/${owner}/${repo}/issues/${index}`, (issue) => { $.get(`${AppSubUrl}/api/v1/repos/${owner}/${repo}/issues/${index}`, (issue) => {
const createdAt = new Date(issue.created_at).toLocaleDateString(undefined, { year: 'numeric', month: 'short', day: 'numeric' });
const createdAt = new Date(issue.created_at).toLocaleDateString(undefined, {year: 'numeric', month: 'short', day: 'numeric'});


let body = issue.body.replace(/\n+/g, ' '); let body = issue.body.replace(/\n+/g, ' ');
if (body.length > 85) { if (body.length > 85) {

+ 1
- 1
web_src/js/features/dropzone.js View File

export default async function createDropzone(el, opts) { export default async function createDropzone(el, opts) {
const [{ default: Dropzone }] = await Promise.all([
const [{default: Dropzone}] = await Promise.all([
import(/* webpackChunkName: "dropzone" */'dropzone'), import(/* webpackChunkName: "dropzone" */'dropzone'),
import(/* webpackChunkName: "dropzone" */'dropzone/dist/dropzone.css'), import(/* webpackChunkName: "dropzone" */'dropzone/dist/dropzone.css'),
]); ]);

web_src/js/features/gitGraph.js → web_src/js/features/gitgraph.js View File

const graphCanvas = document.getElementById('graph-canvas'); const graphCanvas = document.getElementById('graph-canvas');
if (!graphCanvas) return; if (!graphCanvas) return;


const { default: gitGraph } = await import(/* webpackChunkName: "gitgraph" */'../vendor/gitGraph.js');
const {default: gitGraph} = await import(/* webpackChunkName: "gitgraph" */'../vendor/gitgraph.js');


const graphList = []; const graphList = [];
$('#graph-raw-list li span.node-relation').each(function () { $('#graph-raw-list li span.node-relation').each(function () {

web_src/js/features/userHeatmap.js → web_src/js/features/userheatmap.js View File

import Vue from 'vue'; import Vue from 'vue';


const { AppSubUrl, heatmapUser } = window.config;
const {AppSubUrl, heatmapUser} = window.config;


export default async function initHeatmap() { export default async function initHeatmap() {
const el = document.getElementById('user-heatmap'); const el = document.getElementById('user-heatmap');
if (!el) return; if (!el) return;


const { CalendarHeatmap } = await import(/* webpackChunkName: "userheatmap" */'vue-calendar-heatmap');
const {CalendarHeatmap} = await import(/* webpackChunkName: "userheatmap" */'vue-calendar-heatmap');
Vue.component('calendarHeatmap', CalendarHeatmap); Vue.component('calendarHeatmap', CalendarHeatmap);


const vueDelimeters = ['${', '}']; const vueDelimeters = ['${', '}'];
const chartData = []; const chartData = [];
for (let i = 0; i < chartRawData.length; i++) { for (let i = 0; i < chartRawData.length; i++) {
self.totalContributions += chartRawData[i].contributions; self.totalContributions += chartRawData[i].contributions;
chartData[i] = { date: new Date(chartRawData[i].timestamp * 1000), count: chartRawData[i].contributions };
chartData[i] = {date: new Date(chartRawData[i].timestamp * 1000), count: chartRawData[i].contributions};
} }
self.values = chartData; self.values = chartData;
self.isLoading = false; self.isLoading = false;

+ 63
- 77
web_src/js/index.js View File

/* exported timeAddManual, toggleStopwatch, cancelStopwatch */ /* exported timeAddManual, toggleStopwatch, cancelStopwatch */
/* exported toggleDeadlineForm, setDeadline, updateDeadline, deleteDependencyModal, cancelCodeComment, onOAuthLoginClick */ /* exported toggleDeadlineForm, setDeadline, updateDeadline, deleteDependencyModal, cancelCodeComment, onOAuthLoginClick */


import './publicPath.js';
import './publicpath.js';
import './polyfills.js'; import './polyfills.js';


import Vue from 'vue'; import Vue from 'vue';
import 'jquery.are-you-sure'; import 'jquery.are-you-sure';
import './vendor/semanticDropdown.js';
import { svg } from './utils.js';
import './vendor/semanticdropdown.js';
import {svg} from './utils.js';


import initContextPopups from './features/contextPopup.js';
import initContextPopups from './features/contextpopup.js';
import initHighlight from './features/highlight.js'; import initHighlight from './features/highlight.js';
import initGitGraph from './features/gitGraph.js';
import initGitGraph from './features/gitgraph.js';
import initClipboard from './features/clipboard.js'; import initClipboard from './features/clipboard.js';
import initUserHeatmap from './features/userHeatmap.js';
import initUserHeatmap from './features/userheatmap.js';
import createDropzone from './features/dropzone.js'; import createDropzone from './features/dropzone.js';

import ActivityTopAuthors from './components/ActivityTopAuthors.vue'; import ActivityTopAuthors from './components/ActivityTopAuthors.vue';


const { AppSubUrl, StaticUrlPrefix, csrf } = window.config;
const {AppSubUrl, StaticUrlPrefix, csrf} = window.config;


function htmlEncode(text) { function htmlEncode(text) {
return jQuery('<div />').text(text).html(); return jQuery('<div />').text(text).html();
}); });
} }



function initEditForm() { function initEditForm() {
if ($('.edit.form').length === 0) { if ($('.edit.form').length === 0) {
return; return;
reactions = '.reactions > '; reactions = '.reactions > ';
} }


parent.find(`${reactions}a.label`).popup({ position: 'bottom left', metadata: { content: 'title', title: 'none' } });
parent.find(`${reactions}a.label`).popup({position: 'bottom left', metadata: {content: 'title', title: 'none'}});


parent.find(`.select-reaction > .menu > .item, ${reactions}a.label`).on('click', function (e) { parent.find(`.select-reaction > .menu > .item, ${reactions}a.label`).on('click', function (e) {
const vm = this; const vm = this;


if ($(this).hasClass('disabled')) return; if ($(this).hasClass('disabled')) return;


const actionURL = $(this).hasClass('item')
? $(this).closest('.select-reaction').data('action-url')
: $(this).data('action-url');
const actionURL = $(this).hasClass('item') ? $(this).closest('.select-reaction').data('action-url') : $(this).data('action-url');
const url = `${actionURL}/${$(this).hasClass('blue') ? 'unreact' : 'react'}`; const url = `${actionURL}/${$(this).hasClass('blue') ? 'unreact' : 'react'}`;
$.ajax({ $.ajax({
type: 'POST', type: 'POST',
if (field.selectionStart || field.selectionStart === 0) { if (field.selectionStart || field.selectionStart === 0) {
const startPos = field.selectionStart; const startPos = field.selectionStart;
const endPos = field.selectionEnd; const endPos = field.selectionEnd;
field.value = field.value.substring(0, startPos)
+ value
+ field.value.substring(endPos, field.value.length);
field.value = field.value.substring(0, startPos) + value + field.value.substring(endPos, field.value.length);
field.selectionStart = startPos + value.length; field.selectionStart = startPos + value.length;
field.selectionEnd = startPos + value.length; field.selectionEnd = startPos + value.length;
} else { } else {
return; return;
} }


const { items } = pasteEvent.clipboardData;
const {items} = pasteEvent.clipboardData;
if (typeof items === 'undefined') { if (typeof items === 'undefined') {
return; return;
} }


for (let i = 0; i < items.length; i++) { for (let i = 0; i < items.length; i++) {
if (items[i].type.indexOf('image') === -1) continue;
if (!items[i].type.includes('image')) continue;
const blob = items[i].getAsFile(); const blob = items[i].getAsFile();


if (typeof (callback) === 'function') { if (typeof (callback) === 'function') {
function uploadFile(file, callback) { function uploadFile(file, callback) {
const xhr = new XMLHttpRequest(); const xhr = new XMLHttpRequest();


xhr.onload = function () {
xhr.addEventListener('load', () => {
if (xhr.status === 200) { if (xhr.status === 200) {
callback(xhr.responseText); callback(xhr.responseText);
} }
};
});


xhr.open('post', `${AppSubUrl}/attachments`, true); xhr.open('post', `${AppSubUrl}/attachments`, true);
xhr.setRequestHeader('X-Csrf-Token', csrf); xhr.setRequestHeader('X-Csrf-Token', csrf);
htmlEncode($(this).text())}</a>`); htmlEncode($(this).text())}</a>`);
break; break;
case '#assignee_id': case '#assignee_id':
$list.find('.selected').html(`<a class="item" href=${$(this).data('href')}>`
+ `<img class="ui avatar image" src=${$(this).data('avatar')}>${
$list.find('.selected').html(`<a class="item" href=${$(this).data('href')}>` +
`<img class="ui avatar image" src=${$(this).data('avatar')}>${
htmlEncode($(this).text())}</a>`); htmlEncode($(this).text())}</a>`);
} }
$(`.ui${select_id}.list .no-select`).addClass('hide'); $(`.ui${select_id}.list .no-select`).addClass('hide');
window.location.href = $choice.data('url'); window.location.href = $choice.data('url');
} }
}, },
message: { noResults: $dropdown.data('no-results') }
message: {noResults: $dropdown.data('no-results')}
}); });
} }


$.post(update_url, { $.post(update_url, {
_csrf: csrf, _csrf: csrf,
target_branch: targetBranch target_branch: targetBranch
})
.success((data) => {
$branchTarget.text(data.base_branch);
})
.always(() => {
reload();
});
}).success((data) => {
$branchTarget.text(data.base_branch);
}).always(() => {
reload();
});
}; };


const pullrequest_target_update_url = $(this).data('target-update-url'); const pullrequest_target_update_url = $(this).data('target-update-url');
$.post($(this).data('update-url'), { $.post($(this).data('update-url'), {
_csrf: csrf, _csrf: csrf,
title: $editInput.val() title: $editInput.val()
},
(data) => {
}, (data) => {
$editInput.val(data.title); $editInput.val(data.title);
$issueTitle.text(data.title); $issueTitle.text(data.title);
pullrequest_targetbranch_change(pullrequest_target_update_url); pullrequest_targetbranch_change(pullrequest_target_update_url);
const filenameDict = {}; const filenameDict = {};
dz = await createDropzone($dropzone[0], { dz = await createDropzone($dropzone[0], {
url: $dropzone.data('upload-url'), url: $dropzone.data('upload-url'),
headers: { 'X-Csrf-Token': csrf },
headers: {'X-Csrf-Token': csrf},
maxFiles: $dropzone.data('max-file'), maxFiles: $dropzone.data('max-file'),
maxFilesize: $dropzone.data('max-size'), maxFilesize: $dropzone.data('max-size'),
acceptedFiles: ($dropzone.data('accepts') === '*/*') ? null : $dropzone.data('accepts'), acceptedFiles: ($dropzone.data('accepts') === '*/*') ? null : $dropzone.data('accepts'),
const toggleMigrations = function () { const toggleMigrations = function () {
const authUserName = $('#auth_username').val(); const authUserName = $('#auth_username').val();
const cloneAddr = $('#clone_addr').val(); const cloneAddr = $('#clone_addr').val();
if (!$('#mirror').is(':checked') && (authUserName && authUserName.length > 0)
&& (cloneAddr !== undefined && (cloneAddr.startsWith('https://github.com') || cloneAddr.startsWith('http://github.com')))) {
if (!$('#mirror').is(':checked') && (authUserName && authUserName.length > 0) &&
(cloneAddr !== undefined && (cloneAddr.startsWith('https://github.com') || cloneAddr.startsWith('http://github.com')))) {
$('#migrate_items').show(); $('#migrate_items').show();
} else { } else {
$('#migrate_items').hide(); $('#migrate_items').hide();
.on('mouseenter', function () { .on('mouseenter', function () {
const parent = $(this).closest('td'); const parent = $(this).closest('td');
$(this).closest('tr').addClass( $(this).closest('tr').addClass(
parent.hasClass('lines-num-old') || parent.hasClass('lines-code-old')
? 'focus-lines-old' : 'focus-lines-new'
parent.hasClass('lines-num-old') || parent.hasClass('lines-code-old') ? 'focus-lines-old' : 'focus-lines-new'
); );
}) })
.on('mouseleave', function () { .on('mouseleave', function () {
let ntr = tr.next(); let ntr = tr.next();
if (!ntr.hasClass('add-comment')) { if (!ntr.hasClass('add-comment')) {
ntr = $(`<tr class="add-comment">${ ntr = $(`<tr class="add-comment">${
isSplit ? '<td class="lines-num"></td><td class="lines-type-marker"></td><td class="add-comment-left"></td><td class="lines-num"></td><td class="lines-type-marker"></td><td class="add-comment-right"></td>'
: '<td class="lines-num"></td><td class="lines-num"></td><td class="lines-type-marker"></td><td class="add-comment-left add-comment-right"></td>'
isSplit ? '<td class="lines-num"></td><td class="lines-type-marker"></td><td class="add-comment-left"></td><td class="lines-num"></td><td class="lines-type-marker"></td><td class="add-comment-right"></td>' :
'<td class="lines-num"></td><td class="lines-num"></td><td class="lines-type-marker"></td><td class="add-comment-left add-comment-right"></td>'
}</tr>`); }</tr>`);
tr.after(ntr); tr.after(ntr);
} }
// FIXME: still send render request when return back to edit mode // FIXME: still send render request when return back to edit mode
const render = function () { const render = function () {
sideBySideChanges = 0; sideBySideChanges = 0;
if (sideBySideTimeout != null) {
if (sideBySideTimeout !== null) {
clearTimeout(sideBySideTimeout); clearTimeout(sideBySideTimeout);
sideBySideTimeout = null; sideBySideTimeout = null;
} }
mode: 'gfm', mode: 'gfm',
context: $editArea.data('context'), context: $editArea.data('context'),
text: plainText text: plainText
},
(data) => {
}, (data) => {
preview.innerHTML = `<div class="markdown ui segment">${data}</div>`; preview.innerHTML = `<div class="markdown ui segment">${data}</div>`;
emojify.run($('.editor-preview')[0]); emojify.run($('.editor-preview')[0]);
$(preview).find('pre code').each((_, e) => { $(preview).find('pre code').each((_, e) => {
render(); render();
} }
// or delay preview by timeout // or delay preview by timeout
if (sideBySideTimeout != null) {
if (sideBySideTimeout !== null) {
clearTimeout(sideBySideTimeout); clearTimeout(sideBySideTimeout);
sideBySideTimeout = null; sideBySideTimeout = null;
} }
mode: 'gfm', mode: 'gfm',
context: $editArea.data('context'), context: $editArea.data('context'),
text: plainText text: plainText
},
(data) => {
}, (data) => {
preview.innerHTML = `<div class="markdown ui segment">${data}</div>`; preview.innerHTML = `<div class="markdown ui segment">${data}</div>`;
emojify.run($('.editor-preview')[0]); emojify.run($('.editor-preview')[0]);
}); });
apiCall = extension; apiCall = extension;
} }


if (previewLink.length && apiCall && previewFileModes && previewFileModes.length && previewFileModes.indexOf(apiCall) >= 0) {
if (previewLink.length && apiCall && previewFileModes && previewFileModes.length && previewFileModes.includes(apiCall)) {
dataUrl = previewLink.data('url'); dataUrl = previewLink.data('url');
previewLink.data('url', dataUrl.replace(/(.*)\/.*/i, `$1/${mode}`)); previewLink.data('url', dataUrl.replace(/(.*)\/.*/i, `$1/${mode}`));
previewLink.show(); previewLink.show();
} }


// If this file is a Markdown extensions, we will load that editor and return // If this file is a Markdown extensions, we will load that editor and return
if (markdownFileExts.indexOf(extWithDot) >= 0) {
if (markdownFileExts.includes(extWithDot)) {
if (setSimpleMDE($editArea)) { if (setSimpleMDE($editArea)) {
return; return;
} }
CodeMirror.autoLoadMode(codeMirrorEditor, mode); CodeMirror.autoLoadMode(codeMirrorEditor, mode);
} }


if (lineWrapExtensions.indexOf(extWithDot) >= 0) {
if (lineWrapExtensions.includes(extWithDot)) {
codeMirrorEditor.setOption('lineWrapping', true); codeMirrorEditor.setOption('lineWrapping', true);
} else { } else {
codeMirrorEditor.setOption('lineWrapping', false); codeMirrorEditor.setOption('lineWrapping', false);
// - https://codemirror.net/doc/manual.html#keymaps // - https://codemirror.net/doc/manual.html#keymaps
codeMirrorEditor.setOption('extraKeys', { codeMirrorEditor.setOption('extraKeys', {
Tab(cm) { Tab(cm) {
const spaces = Array(parseInt(cm.getOption('indentUnit')) + 1).join(' ');
const spaces = new Array(parseInt(cm.getOption('indentUnit')) + 1).join(' ');
cm.replaceSelection(spaces); cm.replaceSelection(spaces);
} }
}); });
}); });
}); });


return { results: items };
return {results: items};
} }
}, },
searchFields: ['login', 'full_name'], searchFields: ['login', 'full_name'],
minCharacters: 2, minCharacters: 2,
apiSettings: { apiSettings: {
url: `${AppSubUrl}/api/v1/orgs/${$searchTeamBox.data('org')}/teams/search?q={query}`, url: `${AppSubUrl}/api/v1/orgs/${$searchTeamBox.data('org')}/teams/search?q={query}`,
headers: { 'X-Csrf-Token': csrf },
headers: {'X-Csrf-Token': csrf},
onResponse(response) { onResponse(response) {
const items = []; const items = [];
$.each(response.data, (_i, item) => { $.each(response.data, (_i, item) => {
}); });
}); });


return { results: items };
return {results: items};
} }
}, },
searchFields: ['name', 'description'], searchFields: ['name', 'description'],
}); });
}); });


return { results: items };
return {results: items};
} }
}, },
searchFields: ['full_name'], searchFields: ['full_name'],
} }
}).trigger('hashchange'); }).trigger('hashchange');
} }
$('.fold-code').on('click', ({ target }) => {
$('.fold-code').on('click', ({target}) => {
const box = target.closest('.file-content'); const box = target.closest('.file-content');
const folded = box.dataset.folded !== 'true'; const folded = box.dataset.folded !== 'true';
target.classList.add(`fa-chevron-${folded ? 'right' : 'down'}`); target.classList.add(`fa-chevron-${folded ? 'right' : 'down'}`);
const $row = $blob.parent().parent(); const $row = $blob.parent().parent();
$.get(`${$blob.data('url')}?${$blob.data('query')}&anchor=${$blob.data('anchor')}`, (blob) => { $.get(`${$blob.data('url')}?${$blob.data('query')}&anchor=${$blob.data('anchor')}`, (blob) => {
$row.replaceWith(blob); $row.replaceWith(blob);
$(`[data-anchor="${$blob.data('anchor')}"]`).on('click', (e) => { insertBlobExcerpt(e); });
$(`[data-anchor="${$blob.data('anchor')}"]`).on('click', (e) => { insertBlobExcerpt(e) });
$('.diff-detail-box.ui.sticky').sticky(); $('.diff-detail-box.ui.sticky').sticky();
}); });
} }
$('.ui.blob-excerpt').on('click', (e) => { insertBlobExcerpt(e); });
$('.ui.blob-excerpt').on('click', (e) => { insertBlobExcerpt(e) });
} }


function initU2FAuth() { function initU2FAuth() {
$.ajax({ $.ajax({
url: `${AppSubUrl}/user/u2f/sign`, url: `${AppSubUrl}/user/u2f/sign`,
type: 'POST', type: 'POST',
headers: { 'X-Csrf-Token': csrf },
headers: {'X-Csrf-Token': csrf},
data: JSON.stringify(resp), data: JSON.stringify(resp),
contentType: 'application/json; charset=utf-8', contentType: 'application/json; charset=utf-8',
}).done((res) => { }).done((res) => {
$.ajax({ $.ajax({
url: `${AppSubUrl}/user/settings/security/u2f/register`, url: `${AppSubUrl}/user/settings/security/u2f/register`,
type: 'POST', type: 'POST',
headers: { 'X-Csrf-Token': csrf },
headers: {'X-Csrf-Token': csrf},
data: JSON.stringify(resp), data: JSON.stringify(resp),
contentType: 'application/json; charset=utf-8', contentType: 'application/json; charset=utf-8',
success() { success() {
return true; return true;
} }



function u2fError(errorType) { function u2fError(errorType) {
const u2fErrors = { const u2fErrors = {
browser: $('#unsupported-browser'), browser: $('#unsupported-browser'),
} }


function initU2FRegister() { function initU2FRegister() {
$('#register-device').modal({ allowMultiple: false });
$('#u2f-error').modal({ allowMultiple: false });
$('#register-device').modal({allowMultiple: false});
$('#u2f-error').modal({allowMultiple: false});
$('#register-security-key').on('click', (e) => { $('#register-security-key').on('click', (e) => {
e.preventDefault(); e.preventDefault();
u2fApi.ensureSupport() u2fApi.ensureSupport()
apiSettings: { apiSettings: {
url: `${AppSubUrl}/api/v1/repos/search?q={query}&template=true&priority_owner_id=${$('#uid').val()}`, url: `${AppSubUrl}/api/v1/repos/search?q={query}&template=true&priority_owner_id=${$('#uid').val()}`,
onResponse(response) { onResponse(response) {
const filteredResponse = { success: true, results: [] };
const filteredResponse = {success: true, results: []};
filteredResponse.results.push({ filteredResponse.results.push({
name: '', name: '',
value: '' value: ''


await createDropzone('#dropzone', { await createDropzone('#dropzone', {
url: $dropzone.data('upload-url'), url: $dropzone.data('upload-url'),
headers: { 'X-Csrf-Token': csrf },
headers: {'X-Csrf-Token': csrf},
maxFiles: $dropzone.data('max-file'), maxFiles: $dropzone.data('max-file'),
maxFilesize: $dropzone.data('max-size'), maxFilesize: $dropzone.data('max-size'),
acceptedFiles: ($dropzone.data('accepts') === '*/*') ? null : $dropzone.data('accepts'), acceptedFiles: ($dropzone.data('accepts') === '*/*') ? null : $dropzone.data('accepts'),
}); });


$('.issue-action').click(function () { $('.issue-action').click(function () {
let { action } = this.dataset;
let { elementId } = this.dataset;
let {action} = this.dataset;
let {elementId} = this.dataset;
const issueIDs = $('.issue-checkbox').children('input:checked').map(function () { const issueIDs = $('.issue-checkbox').children('input:checked').map(function () {
return this.dataset.issueId; return this.dataset.issueId;
}).get().join(); }).get().join();
const { url } = this.dataset;
const {url} = this.dataset;
if (elementId === '0' && url.substr(-9) === '/assignee') { if (elementId === '0' && url.substr(-9) === '/assignee') {
elementId = ''; elementId = '';
action = 'clear'; action = 'clear';
// NOTICE: This reset of checkbox state targets Firefox caching behaviour, as the checkboxes stay checked after reload // NOTICE: This reset of checkbox state targets Firefox caching behaviour, as the checkboxes stay checked after reload
if (action === 'close' || action === 'open') { if (action === 'close' || action === 'open') {
// uncheck all checkboxes // uncheck all checkboxes
$('.issue-checkbox input[type="checkbox"]').each((_, e) => { e.checked = false; });
$('.issue-checkbox input[type="checkbox"]').each((_, e) => { e.checked = false });
} }
reload(); reload();
}); });
const vm = this; const vm = this;


const items = vm.items.filter((item) => { const items = vm.items.filter((item) => {
return ((vm.mode === 'branches' && item.branch) || (vm.mode === 'tags' && item.tag))
&& (!vm.searchTerm || item.name.toLowerCase().indexOf(vm.searchTerm.toLowerCase()) >= 0);
return ((vm.mode === 'branches' && item.branch) || (vm.mode === 'tags' && item.tag)) &&
(!vm.searchTerm || item.name.toLowerCase().includes(vm.searchTerm.toLowerCase()));
}); });


vm.active = (items.length === 0 && vm.showCreateNewBranch ? 0 : -1); vm.active = (items.length === 0 && vm.showCreateNewBranch ? 0 : -1);
if (xhr.responseJSON.invalidTopics.length > 0) { if (xhr.responseJSON.invalidTopics.length > 0) {
topicPrompts.formatPrompt = xhr.responseJSON.message; topicPrompts.formatPrompt = xhr.responseJSON.message;


const { invalidTopics } = xhr.responseJSON;
const {invalidTopics} = xhr.responseJSON;
const topicLables = topicDropdown.children('a.ui.label'); const topicLables = topicDropdown.children('a.ui.label');


topics.split(',').forEach((value, index) => { topics.split(',').forEach((value, index) => {
topicDropdown.dropdown({ topicDropdown.dropdown({
allowAdditions: true, allowAdditions: true,
forceSelection: false, forceSelection: false,
fields: { name: 'description', value: 'data-value' },
fields: {name: 'description', value: 'data-value'},
saveRemoteData: false, saveRemoteData: false,
label: { label: {
transition: 'horizontal flip', transition: 'horizontal flip',
const query = stripTags(this.urlData.query.trim()); const query = stripTags(this.urlData.query.trim());
let found_query = false; let found_query = false;
const current_topics = []; const current_topics = [];
topicDropdown.find('div.label.visible.topic,a.label.visible').each((_, e) => { current_topics.push(e.dataset.value); });
topicDropdown.find('div.label.visible.topic,a.label.visible').each((_, e) => { current_topics.push(e.dataset.value) });


if (res.topics) { if (res.topics) {
let found = false; let found = false;
for (let i = 0; i < res.topics.length; i++) { for (let i = 0; i < res.topics.length; i++) {
// skip currently added tags // skip currently added tags
if (current_topics.indexOf(res.topics[i].topic_name) !== -1) {
if (current_topics.includes(res.topics[i].topic_name)) {
continue; continue;
} }


if (res.topics[i].topic_name.toLowerCase() === query.toLowerCase()) { if (res.topics[i].topic_name.toLowerCase() === query.toLowerCase()) {
found_query = true; found_query = true;
} }
formattedResponse.results.push({ description: res.topics[i].topic_name, 'data-value': res.topics[i].topic_name });
formattedResponse.results.push({description: res.topics[i].topic_name, 'data-value': res.topics[i].topic_name});
found = true; found = true;
} }
formattedResponse.success = found; formattedResponse.success = found;


if (query.length > 0 && !found_query) { if (query.length > 0 && !found_query) {
formattedResponse.success = true; formattedResponse.success = true;
formattedResponse.results.unshift({ description: query, 'data-value': query });
formattedResponse.results.unshift({description: query, 'data-value': query});
} else if (query.length > 0 && found_query) { } else if (query.length > 0 && found_query) {
formattedResponse.results.sort((a, b) => { formattedResponse.results.sort((a, b) => {
if (a.description.toLowerCase() === query.toLowerCase()) return -1; if (a.description.toLowerCase() === query.toLowerCase()) return -1;
}); });
} }



return formattedResponse; return formattedResponse;
}, },
}, },
apiSettings: { apiSettings: {
url: issueSearchUrl, url: issueSearchUrl,
onResponse(response) { onResponse(response) {
const filteredResponse = { success: true, results: [] };
const filteredResponse = {success: true, results: []};
const currIssueId = $('#new-dependency-drop-list').data('issue-id'); const currIssueId = $('#new-dependency-drop-list').data('issue-id');
// Parse the response from the api to work with our dropdown // Parse the response from the api to work with our dropdown
$.each(response, (_i, issue) => { $.each(response, (_i, issue) => {

web_src/js/publicPath.js → web_src/js/publicpath.js View File

/* This sets up webpack's chunk loading to load resources from the 'public'
directory. This file must be imported before any lazy-loading is being attempted. */
// This sets up webpack's chunk loading to load resources from the 'public'
// directory. This file must be imported before any lazy-loading is being attempted.


if (document.currentScript && document.currentScript.src) { if (document.currentScript && document.currentScript.src) {
const url = new URL(document.currentScript.src); const url = new URL(document.currentScript.src);

web_src/js/vendor/gitGraph.js → web_src/js/vendor/gitgraph.js View File


web_src/js/vendor/semanticDropdown.js → web_src/js/vendor/semanticdropdown.js View File


+ 6
- 6
webpack.config.js View File

const SpriteLoaderPlugin = require('svg-sprite-loader/plugin'); const SpriteLoaderPlugin = require('svg-sprite-loader/plugin');
const TerserPlugin = require('terser-webpack-plugin'); const TerserPlugin = require('terser-webpack-plugin');
const VueLoaderPlugin = require('vue-loader/lib/plugin'); const VueLoaderPlugin = require('vue-loader/lib/plugin');
const { statSync } = require('fs');
const { resolve, parse } = require('path');
const { SourceMapDevToolPlugin } = require('webpack');
const {statSync} = require('fs');
const {resolve, parse} = require('path');
const {SourceMapDevToolPlugin} = require('webpack');


const glob = (pattern) => fastGlob.sync(pattern, { cwd: __dirname, absolute: true });
const glob = (pattern) => fastGlob.sync(pattern, {cwd: __dirname, absolute: true});


const themes = {}; const themes = {};
for (const path of glob('web_src/less/themes/*.less')) { for (const path of glob('web_src/less/themes/*.less')) {
extract: true, extract: true,
spriteFilename: 'img/svg/icons.svg', spriteFilename: 'img/svg/icons.svg',
symbolId: (path) => { symbolId: (path) => {
const { name } = parse(path);
const {name} = parse(path);
if (/@primer[/\\]octicons/.test(path)) { if (/@primer[/\\]octicons/.test(path)) {
return `octicon-${name}`; return `octicon-${name}`;
} }
}), }),
new CopyPlugin([ new CopyPlugin([
// workaround for https://github.com/go-gitea/gitea/issues/10653 // workaround for https://github.com/go-gitea/gitea/issues/10653
{ from: 'node_modules/fomantic-ui/dist/semantic.min.css', to: 'fomantic/semantic.min.css' },
{from: 'node_modules/fomantic-ui/dist/semantic.min.css', to: 'fomantic/semantic.min.css'},
]), ]),
], ],
performance: { performance: {

Loading…
Cancel
Save