/* globals wipPrefixes */
/* exported timeAddManual, toggleStopwatch, cancelStopwatch */
/* exported toggleDeadlineForm, setDeadline, updateDeadline, deleteDependencyModal, cancelCodeComment, onOAuthLoginClick */
import './publicpath.js';
import './polyfills.js';
import './features/letteravatar.js'
import Vue from 'vue';
import ElementUI from 'element-ui';
import 'element-ui/lib/theme-chalk/index.css';
import axios from 'axios';
import qs from 'qs';
import 'jquery.are-you-sure';
import './vendor/semanticdropdown.js';
import {svg} from './utils.js';
import echarts from 'echarts'
import initContextPopups from './features/contextpopup.js';
import initGitGraph from './features/gitgraph.js';
import initClipboard from './features/clipboard.js';
import initUserHeatmap from './features/userheatmap.js';
import initDateTimePicker from './features/datetimepicker.js';
import {
initTribute,
issuesTribute,
emojiTribute
} from './features/tribute.js';
import createDropzone from './features/dropzone.js';
import highlight from './features/highlight.js';
import ActivityTopAuthors from './components/ActivityTopAuthors.vue';
import {
initNotificationsTable,
initNotificationCount
} from './features/notification.js';
import {createCodeEditor} from './features/codeeditor.js';
import MinioUploader from './components/MinioUploader.vue';
import ObsUploader from './components/ObsUploader.vue';
import EditAboutInfo from './components/EditAboutInfo.vue';
import Images from './components/Images.vue';
import EditTopics from './components/EditTopics.vue';
import DataAnalysis from './components/DataAnalysis.vue'
import Contributors from './components/Contributors.vue'
import Model from './components/Model.vue';
Vue.use(ElementUI);
Vue.prototype.$axios = axios;
Vue.prototype.qs = qs;
const {AppSubUrl, StaticUrlPrefix, csrf} = window.config;
Object.defineProperty(Vue.prototype, '$echarts', {
value: echarts
})
function htmlEncode(text) {
return jQuery('
element clickable like a link
$('tr[data-href]').on('click', function () {
window.location = $(this).data('href');
});
// make table element clickable like a link
$('td[data-href]').click(function () {
window.location = $(this).data('href');
});
// Dropzone
const $dropzone = $('#dropzone');
if ($dropzone.length > 0) {
const filenameDict = {};
await createDropzone('#dropzone', {
url: $dropzone.data('upload-url'),
headers: {'X-Csrf-Token': csrf},
maxFiles: $dropzone.data('max-file'),
maxFilesize: $dropzone.data('max-size'),
acceptedFiles:
$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'),
init() {
this.on('success', (file, data) => {
filenameDict[file.name] = data.uuid;
const input = $(
``
).val(data.uuid);
$('.files').append(input);
});
this.on('removedfile', (file) => {
if (file.name in filenameDict) {
$(`#${filenameDict[file.name]}`).remove();
}
if ($dropzone.data('remove-url') && $dropzone.data('csrf')) {
$.post($dropzone.data('remove-url'), {
file: filenameDict[file.name],
_csrf: $dropzone.data('csrf')
});
}
});
}
});
}
// Helpers.
$('.delete-button').on('click', showDeletePopup);
$('.add-all-button').on('click', showAddAllPopup);
$('.link-action').on('click', linkAction);
$('.link-email-action').on('click', linkEmailAction);
$('.delete-branch-button').on('click', showDeletePopup);
$('.undo-button').on('click', function () {
const $this = $(this);
$.post($this.data('url'), {
_csrf: csrf,
id: $this.data('id')
}).done((data) => {
window.location.href = data.redirect;
});
});
$('.show-panel.button').on('click', function () {
$($(this).data('panel')).show();
});
$('.show-modal.button').on('click', function () {
$($(this).data('modal')).modal('show');
});
$('.delete-post.button').on('click', function () {
const $this = $(this);
$.post($this.data('request-url'), {
_csrf: csrf
}).done(() => {
window.location.href = $this.data('done-url');
});
});
// Set anchor.
$('.markdown').each(function () {
$(this)
.find('h1, h2, h3, h4, h5, h6')
.each(function () {
let node = $(this);
node = node.wrap('');
node.append(
`${svg('octicon-link', 16)}`
);
});
});
$('.issue-checkbox').on('click', () => {
const numChecked = $('.issue-checkbox').children('input:checked').length;
if (numChecked > 0) {
$('#issue-filters').addClass('hide');
$('#issue-actions').removeClass('hide');
} else {
$('#issue-filters').removeClass('hide');
$('#issue-actions').addClass('hide');
}
});
$('.issue-action').on('click', function () {
let {action} = this.dataset;
let {elementId} = this.dataset;
const issueIDs = $('.issue-checkbox')
.children('input:checked')
.map(function () {
return this.dataset.issueId;
})
.get()
.join();
const {url} = this.dataset;
if (elementId === '0' && url.substr(-9) === '/assignee') {
elementId = '';
action = 'clear';
}
updateIssuesMeta(url, action, issueIDs, elementId, '').then(() => {
// NOTICE: This reset of checkbox state targets Firefox caching behaviour, as the checkboxes stay checked after reload
if (action === 'close' || action === 'open') {
// uncheck all checkboxes
$('.issue-checkbox input[type="checkbox"]').each((_, e) => {
e.checked = false;
});
}
reload();
});
});
// NOTICE: This event trigger targets Firefox caching behaviour, as the checkboxes stay checked after reload
// trigger ckecked event, if checkboxes are checked on load
$('.issue-checkbox input[type="checkbox"]:checked')
.first()
.each((_, e) => {
e.checked = false;
$(e).trigger('click');
});
$('.resolve-conversation').on('click', function (e) {
e.preventDefault();
const id = $(this).data('comment-id');
const action = $(this).data('action');
const url = $(this).data('update-url');
$.post(url, {
_csrf: csrf,
action,
comment_id: id
}).then(reload);
});
buttonsClickOnEnter();
searchUsers();
searchTeams();
searchRepositories();
initCommentForm();
initInstall();
initRepository();
initMigration();
initWikiForm();
initEditForm();
initEditor();
initOrganization();
initGithook();
initWebhook();
initAdmin();
initCodeView();
initVueApp();
initVueUploader();
initObsUploader();
initVueEditAbout();
initVueEditTopic();
initVueContributors();
initVueImages();
initVueModel();
initVueDataAnalysis();
initTeamSettings();
initCtrlEnterSubmit();
initNavbarContentToggle();
// initTopicbar();vim
// closeTopicbar();
initU2FAuth();
initU2FRegister();
initIssueList();
initWipTitle();
initPullRequestReview();
initRepoStatusChecker();
initTemplateSearch();
initContextPopups();
initNotificationsTable();
initNotificationCount();
initTribute();
initDropDown();
// Repo clone url.
if ($('#repo-clone-url').length > 0) {
switch (localStorage.getItem('repo-clone-protocol')) {
case 'ssh':
if ($('#repo-clone-ssh').length === 0) {
$('#repo-clone-https').trigger('click');
}
break;
default:
$('#repo-clone-https').trigger('click');
break;
}
}
const routes = {
'div.user.settings': initUserSettings,
'div.repository.settings.collaboration': initRepositoryCollaboration
};
let selector;
for (selector in routes) {
if ($(selector).length > 0) {
routes[selector]();
break;
}
}
const $cloneAddr = $('#clone_addr');
$cloneAddr.on('change', () => {
const $repoName = $('#alias');
const $owner = $('#ownerDropdown div.text').attr("title")
const $urlAdd = location.href.split('/')[0] + '//' + location.href.split('/')[2]
if ($cloneAddr.val().length > 0 && $repoName.val().length === 0) {
// Only modify if repo_name input is blank
const repoValue = $cloneAddr.val().match(/^(.*\/)?((.+?)(\.git)?)$/)[3]
$repoName.val($cloneAddr.val().match(/^(.*\/)?((.+?)(\.git)?)$/)[3]);
$.get(`${window.config.AppSubUrl}/repo/check_name?q=${repoValue}&owner=${$owner}`,(data)=>{
const repo_name = data.name
$('#repo_name').val(repo_name)
repo_name && $('#repo_name').parent().removeClass('error')
$('#repoAdress').css("display","flex")
$('#repoAdress span').text($urlAdd+'/'+$owner+'/'+$('#repo_name').val()+'.git')
$('#repo_name').attr("placeholder","")
})
}
});
// parallel init of lazy-loaded features
await Promise.all([
highlight(document.querySelectorAll('pre code')),
initGitGraph(),
initClipboard(),
initUserHeatmap()
]);
});
function changeHash(hash) {
if (window.history.pushState) {
window.history.pushState(null, null, hash);
} else {
window.location.hash = hash;
}
}
function deSelect() {
if (window.getSelection) {
window.getSelection().removeAllRanges();
} else {
document.selection.empty();
}
}
function selectRange($list, $select, $from) {
$list.removeClass('active');
if ($from) {
let a = parseInt($select.attr('rel').substr(1));
let b = parseInt($from.attr('rel').substr(1));
let c;
if (a !== b) {
if (a > b) {
c = a;
a = b;
b = c;
}
const classes = [];
for (let i = a; i <= b; i++) {
classes.push(`.L${i}`);
}
$list.filter(classes.join(',')).addClass('active');
changeHash(`#L${a}-L${b}`);
return;
}
}
$select.addClass('active');
changeHash(`#${$select.attr('rel')}`);
}
$(() => {
// Warn users that try to leave a page after entering data into a form.
// Except on sign-in pages, and for forms marked as 'ignore-dirty'.
if ($('.user.signin').length === 0) {
$('form:not(.ignore-dirty)').areYouSure();
}
// Parse SSH Key
$('#ssh-key-content').on('change paste keyup', function () {
const arrays = $(this)
.val()
.split(' ');
const $title = $('#ssh-key-title');
if ($title.val() === '' && arrays.length === 3 && arrays[2] !== '') {
$title.val(arrays[2]);
}
});
});
function showDeletePopup() {
const $this = $(this);
let filter = '';
if ($this.attr('id')) {
filter += `#${$this.attr('id')}`;
}
const dialog = $(`.delete.modal${filter}`);
dialog.find('.name').text($this.data('name'));
dialog
.modal({
closable: false,
onApprove() {
if ($this.data('type') === 'form') {
$($this.data('form')).trigger('submit');
return;
}
$.post($this.data('url'), {
_csrf: csrf,
id: $this.data('id')
}).done((data) => {
window.location.href = data.redirect;
});
}
})
.modal('show');
return false;
}
function showAddAllPopup() {
const $this = $(this);
let filter = '';
if ($this.attr('id')) {
filter += `#${$this.attr('id')}`;
}
const dialog = $(`.addall.modal${filter}`);
dialog.find('.name').text($this.data('name'));
dialog
.modal({
closable: false,
onApprove() {
if ($this.data('type') === 'form') {
$($this.data('form')).trigger('submit');
return;
}
$.post($this.data('url'), {
_csrf: csrf,
id: $this.data('id')
}).done((data) => {
window.location.href = data.redirect;
});
}
})
.modal('show');
return false;
}
function linkAction(e) {
e.preventDefault();
const $this = $(this);
const redirect = $this.data('redirect');
$.post($this.data('url'), {
_csrf: csrf
}).done((data) => {
if (data.redirect) {
window.location.href = data.redirect;
} else if (redirect) {
window.location.href = redirect;
} else {
window.location.reload();
}
});
}
function linkEmailAction(e) {
const $this = $(this);
$('#form-uid').val($this.data('uid'));
$('#form-email').val($this.data('email'));
$('#form-primary').val($this.data('primary'));
$('#form-activate').val($this.data('activate'));
$('#form-uid').val($this.data('uid'));
$('#change-email-modal').modal('show');
e.preventDefault();
}
function initVueComponents() {
const vueDelimeters = ['${', '}'];
Vue.component('repo-search', {
delimiters: vueDelimeters,
props: {
searchLimit: {
type: Number,
default: 10
},
suburl: {
type: String,
required: true
},
uid: {
type: Number,
required: true
},
organizations: {
type: Array,
default: []
},
isOrganization: {
type: Boolean,
default: true
},
canCreateOrganization: {
type: Boolean,
default: false
},
organizationsTotalCount: {
type: Number,
default: 0
},
moreReposLink: {
type: String,
default: ''
}
},
data() {
const params = new URLSearchParams(window.location.search);
let tab = params.get('repo-search-tab');
if (!tab) {
tab = 'repos';
}
let reposFilter = params.get('repo-search-filter');
if (!reposFilter) {
reposFilter = 'all';
}
let privateFilter = params.get('repo-search-private');
if (!privateFilter) {
privateFilter = 'both';
}
let archivedFilter = params.get('repo-search-archived');
if (!archivedFilter) {
archivedFilter = 'unarchived';
}
let searchQuery = params.get('repo-search-query');
if (!searchQuery) {
searchQuery = '';
}
let page = 1;
try {
page = parseInt(params.get('repo-search-page'));
} catch {
// noop
}
if (!page) {
page = 1;
}
return {
tab,
repos: [],
reposTotalCount: 0,
reposFilter,
archivedFilter,
privateFilter,
page,
finalPage: 1,
searchQuery,
isLoading: false,
staticPrefix: StaticUrlPrefix,
counts: {},
repoTypes: {
all: {
searchMode: ''
},
forks: {
searchMode: 'fork'
},
mirrors: {
searchMode: 'mirror'
},
sources: {
searchMode: 'source'
},
collaborative: {
searchMode: 'collaborative'
}
}
};
},
computed: {
showMoreReposLink() {
return (
this.repos.length > 0 &&
this.repos.length <
this.counts[
`${this.reposFilter}:${this.archivedFilter}:${this.privateFilter}`
]
);
},
searchURL() {
return `${
this.suburl
}/api/v1/repos/search?sort=updated&order=desc&uid=${this.uid}&q=${
this.searchQuery
}&page=${this.page}&limit=${this.searchLimit}&mode=${
this.repoTypes[this.reposFilter].searchMode
}${this.reposFilter !== 'all' ? '&exclusive=1' : ''}${
this.archivedFilter === 'archived' ? '&archived=true' : ''
}${this.archivedFilter === 'unarchived' ? '&archived=false' : ''}${
this.privateFilter === 'private' ? '&onlyPrivate=true' : ''
}${this.privateFilter === 'public' ? '&private=false' : ''}`;
},
repoTypeCount() {
return this.counts[
`${this.reposFilter}:${this.archivedFilter}:${this.privateFilter}`
];
}
},
mounted() {
this.searchRepos(this.reposFilter);
$(this.$el)
.find('.poping.up')
.popup();
$(this.$el)
.find('.dropdown')
.dropdown();
this.setCheckboxes();
const self = this;
Vue.nextTick(() => {
self.$refs.search.focus();
});
},
methods: {
changeTab(t) {
this.tab = t;
this.updateHistory();
},
setCheckboxes() {
switch (this.archivedFilter) {
case 'unarchived':
$('#archivedFilterCheckbox').checkbox('set unchecked');
break;
case 'archived':
$('#archivedFilterCheckbox').checkbox('set checked');
break;
case 'both':
$('#archivedFilterCheckbox').checkbox('set indeterminate');
break;
default:
this.archivedFilter = 'unarchived';
$('#archivedFilterCheckbox').checkbox('set unchecked');
break;
}
switch (this.privateFilter) {
case 'public':
$('#privateFilterCheckbox').checkbox('set unchecked');
break;
case 'private':
$('#privateFilterCheckbox').checkbox('set checked');
break;
case 'both':
$('#privateFilterCheckbox').checkbox('set indeterminate');
break;
default:
this.privateFilter = 'both';
$('#privateFilterCheckbox').checkbox('set indeterminate');
break;
}
},
changeReposFilter(filter) {
this.reposFilter = filter;
this.repos = [];
this.page = 1;
Vue.set(
this.counts,
`${filter}:${this.archivedFilter}:${this.privateFilter}`,
0
);
this.searchRepos();
},
updateHistory() {
const params = new URLSearchParams(window.location.search);
if (this.tab === 'repos') {
params.delete('repo-search-tab');
} else {
params.set('repo-search-tab', this.tab);
}
if (this.reposFilter === 'all') {
params.delete('repo-search-filter');
} else {
params.set('repo-search-filter', this.reposFilter);
}
if (this.privateFilter === 'both') {
params.delete('repo-search-private');
} else {
params.set('repo-search-private', this.privateFilter);
}
if (this.archivedFilter === 'unarchived') {
params.delete('repo-search-archived');
} else {
params.set('repo-search-archived', this.archivedFilter);
}
if (this.searchQuery === '') {
params.delete('repo-search-query');
} else {
params.set('repo-search-query', this.searchQuery);
}
if (this.page === 1) {
params.delete('repo-search-page');
} else {
params.set('repo-search-page', `${this.page}`);
}
window.history.replaceState({}, '', `?${params.toString()}`);
},
toggleArchivedFilter() {
switch (this.archivedFilter) {
case 'both':
this.archivedFilter = 'unarchived';
break;
case 'unarchived':
this.archivedFilter = 'archived';
break;
case 'archived':
this.archivedFilter = 'both';
break;
default:
this.archivedFilter = 'unarchived';
break;
}
this.page = 1;
this.repos = [];
this.setCheckboxes();
Vue.set(
this.counts,
`${this.reposFilter}:${this.archivedFilter}:${this.privateFilter}`,
0
);
this.searchRepos();
},
togglePrivateFilter() {
switch (this.privateFilter) {
case 'both':
this.privateFilter = 'public';
break;
case 'public':
this.privateFilter = 'private';
break;
case 'private':
this.privateFilter = 'both';
break;
default:
this.privateFilter = 'both';
break;
}
this.page = 1;
this.repos = [];
this.setCheckboxes();
Vue.set(
this.counts,
`${this.reposFilter}:${this.archivedFilter}:${this.privateFilter}`,
0
);
this.searchRepos();
},
changePage(page) {
this.page = page;
if (this.page > this.finalPage) {
this.page = this.finalPage;
}
if (this.page < 1) {
this.page = 1;
}
this.repos = [];
Vue.set(
this.counts,
`${this.reposFilter}:${this.archivedFilter}:${this.privateFilter}`,
0
);
this.searchRepos();
},
showArchivedRepo(repo) {
switch (this.archivedFilter) {
case 'both':
return true;
case 'unarchived':
return !repo.archived;
case 'archived':
return repo.archived;
default:
return !repo.archived;
}
},
showPrivateRepo(repo) {
switch (this.privateFilter) {
case 'both':
return true;
case 'public':
return !repo.private;
case 'private':
return repo.private;
default:
return true;
}
},
showFilteredRepo(repo) {
switch (this.reposFilter) {
case 'sources':
return repo.owner.id === this.uid && !repo.mirror && !repo.fork;
case 'forks':
return repo.owner.id === this.uid && !repo.mirror && repo.fork;
case 'mirrors':
return repo.mirror;
case 'collaborative':
return repo.owner.id !== this.uid && !repo.mirror;
default:
return true;
}
},
showRepo(repo) {
return (
this.showArchivedRepo(repo) &&
this.showPrivateRepo(repo) &&
this.showFilteredRepo(repo)
);
},
searchRepos() {
const self = this;
this.isLoading = true;
const searchedMode = this.repoTypes[this.reposFilter].searchMode;
const searchedURL = this.searchURL;
const searchedQuery = this.searchQuery;
$.getJSON(searchedURL, (result, _textStatus, request) => {
if (searchedURL === self.searchURL) {
self.repos = result.data;
const count = request.getResponseHeader('X-Total-Count');
if (
searchedQuery === '' &&
searchedMode === '' &&
self.archivedFilter === 'both'
) {
self.reposTotalCount = count;
}
Vue.set(
self.counts,
`${self.reposFilter}:${self.archivedFilter}:${self.privateFilter}`,
count
);
self.finalPage = Math.floor(count / self.searchLimit) + 1;
self.updateHistory();
}
}).always(() => {
if (searchedURL === self.searchURL) {
self.isLoading = false;
}
});
},
repoClass(repo) {
if (repo.fork) {
return 'octicon-repo-forked';
}
if (repo.mirror) {
return 'octicon-repo-clone';
}
if (repo.template) {
return `octicon-repo-template${repo.private ? '-private' : ''}`;
}
if (repo.private) {
return 'octicon-lock';
}
return 'octicon-repo';
}
}
});
}
function initCtrlEnterSubmit() {
$('.js-quick-submit').on('keydown', function (e) {
if (
((e.ctrlKey && !e.altKey) || e.metaKey) &&
(e.keyCode === 13 || e.keyCode === 10)
) {
$(this)
.closest('form')
.trigger('submit');
}
});
}
function initVueApp() {
const el = document.getElementById('app');
if (!el) {
return;
}
initVueComponents();
new Vue({
delimiters: ['${', '}'],
el,
data: {
page:parseInt(new URLSearchParams(window.location.search).get('page')),
searchLimit: Number(
(document.querySelector('meta[name=_search_limit]') || {}).content
),
page:1,
suburl: AppSubUrl,
uid: Number(
(document.querySelector('meta[name=_context_uid]') || {}).content
),
activityTopAuthors: window.ActivityTopAuthors || []
},
components: {
ActivityTopAuthors
},
mounted(){
this.page = parseInt(new URLSearchParams(window.location.search).get('page'))
},
methods:{
handleCurrentChange:function (val) {
window.location.href='/admin/cloudbrains?page='+val
this.page = val
}
}
});
}
function initVueUploader() {
const el = document.getElementById('minioUploader');
if (!el) {
return;
}
new Vue({
el: '#minioUploader',
components: {MinioUploader},
template: ''
});
}
function initVueEditAbout() {
const el = document.getElementById('about-desc');
if (!el) {
return;
}
new Vue({
el: '#about-desc',
render: h => h(EditAboutInfo)
});
}
function initVueEditTopic() {
const el = document.getElementById('topic_edit1');
if (!el) {
return;
}
new Vue({
el:'#topic_edit1',
render:h=>h(EditTopics)
})
}
function initVueContributors() {
const el = document.getElementById('Contributors');
if (!el) {
return;
}
new Vue({
el:'#Contributors',
render:h=>h(Contributors)
})
}
function initVueImages() {
const el = document.getElementById('images');
if (!el) {
return;
}
new Vue({
el: '#images',
render: h => h(Images)
});
}
function initVueModel() {
const el = document.getElementById('model_list');
if (!el) {
return;
}
new Vue({
el: el,
render: h => h(Model)
});
}
function initVueDataAnalysis() {
const el = document.getElementById('data_analysis');
if (!el) {
return;
}
new Vue({
el: '#data_analysis',
render: h => h(DataAnalysis)
});
}
// 新增
function initObsUploader() {
const el = document.getElementById('obsUploader');
if (!el) {
return;
}
new Vue({
el: '#obsUploader',
components: {ObsUploader},
template: ''
});
}
window.timeAddManual = function () {
$('.mini.modal')
.modal({
duration: 200,
onApprove() {
$('#add_time_manual_form').trigger('submit');
}
})
.modal('show');
};
window.toggleStopwatch = function () {
$('#toggle_stopwatch_form').trigger('submit');
};
window.cancelStopwatch = function () {
$('#cancel_stopwatch_form').trigger('submit');
};
function initFilterBranchTagDropdown(selector) {
$(selector).each(function () {
const $dropdown = $(this);
const $data = $dropdown.find('.data');
const data = {
items: [],
mode: $data.data('mode'),
searchTerm: '',
noResults: '',
canCreateBranch: false,
menuVisible: false,
active: 0
};
$data.find('.item').each(function () {
data.items.push({
name: $(this).text(),
url: $(this).data('url'),
branch: $(this).hasClass('branch'),
tag: $(this).hasClass('tag'),
selected: $(this).hasClass('selected')
});
});
$data.remove();
new Vue({
delimiters: ['${', '}'],
el: this,
data,
beforeMount() {
const vm = this;
this.noResults = vm.$el.getAttribute('data-no-results');
this.canCreateBranch =
vm.$el.getAttribute('data-can-create-branch') === 'true';
document.body.addEventListener('click', (event) => {
if (vm.$el.contains(event.target)) {
return;
}
if (vm.menuVisible) {
Vue.set(vm, 'menuVisible', false);
}
});
},
watch: {
menuVisible(visible) {
if (visible) {
this.focusSearchField();
}
}
},
computed: {
filteredItems() {
const vm = this;
const items = vm.items.filter((item) => {
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;
return items;
},
showNoResults() {
return this.filteredItems.length === 0 && !this.showCreateNewBranch;
},
showCreateNewBranch() {
const vm = this;
if (!this.canCreateBranch || !vm.searchTerm || vm.mode === 'tags') {
return false;
}
return (
vm.items.filter(
(item) => item.name.toLowerCase() === vm.searchTerm.toLowerCase()
).length === 0
);
}
},
methods: {
selectItem(item) {
const prev = this.getSelected();
if (prev !== null) {
prev.selected = false;
}
item.selected = true;
window.location.href = item.url;
},
createNewBranch() {
if (!this.showCreateNewBranch) {
return;
}
$(this.$refs.newBranchForm).trigger('submit');
},
focusSearchField() {
const vm = this;
Vue.nextTick(() => {
vm.$refs.searchField.focus();
});
},
getSelected() {
for (let i = 0, j = this.items.length; i < j; ++i) {
if (this.items[i].selected) return this.items[i];
}
return null;
},
getSelectedIndexInFiltered() {
for (let i = 0, j = this.filteredItems.length; i < j; ++i) {
if (this.filteredItems[i].selected) return i;
}
return -1;
},
scrollToActive() {
let el = this.$refs[`listItem${this.active}`];
if (!el || el.length === 0) {
return;
}
if (Array.isArray(el)) {
el = el[0];
}
const cont = this.$refs.scrollContainer;
if (el.offsetTop < cont.scrollTop) {
cont.scrollTop = el.offsetTop;
} else if (
el.offsetTop + el.clientHeight >
cont.scrollTop + cont.clientHeight
) {
cont.scrollTop = el.offsetTop + el.clientHeight - cont.clientHeight;
}
},
keydown(event) {
const vm = this;
if (event.keyCode === 40) {
// arrow down
event.preventDefault();
if (vm.active === -1) {
vm.active = vm.getSelectedIndexInFiltered();
}
if (
vm.active + (vm.showCreateNewBranch ? 0 : 1) >=
vm.filteredItems.length
) {
return;
}
vm.active++;
vm.scrollToActive();
}
if (event.keyCode === 38) {
// arrow up
event.preventDefault();
if (vm.active === -1) {
vm.active = vm.getSelectedIndexInFiltered();
}
if (vm.active <= 0) {
return;
}
vm.active--;
vm.scrollToActive();
}
if (event.keyCode === 13) {
// enter
event.preventDefault();
if (vm.active >= vm.filteredItems.length) {
vm.createNewBranch();
} else if (vm.active >= 0) {
vm.selectItem(vm.filteredItems[vm.active]);
}
}
if (event.keyCode === 27) {
// escape
event.preventDefault();
vm.menuVisible = false;
}
}
}
});
});
}
$('.commit-button').on('click', function (e) {
e.preventDefault();
$(this)
.parent()
.find('.commit-body')
.toggle();
});
function initNavbarContentToggle() {
const content = $('#navbar');
const toggle = $('#navbar-expand-toggle');
let isExpanded = false;
toggle.on('click', () => {
isExpanded = !isExpanded;
if (isExpanded) {
content.addClass('shown');
toggle.addClass('active');
} else {
content.removeClass('shown');
toggle.removeClass('active');
}
});
}
window.toggleDeadlineForm = function () {
$('#deadlineForm').fadeToggle(150);
};
window.setDeadline = function () {
const deadline = $('#deadlineDate').val();
window.updateDeadline(deadline);
};
window.updateDeadline = function (deadlineString) {
$('#deadline-err-invalid-date').hide();
$('#deadline-loader').addClass('loading');
let realDeadline = null;
if (deadlineString !== '') {
const newDate = Date.parse(deadlineString);
if (Number.isNaN(newDate)) {
$('#deadline-loader').removeClass('loading');
$('#deadline-err-invalid-date').show();
return false;
}
realDeadline = new Date(newDate);
}
$.ajax(`${$('#update-issue-deadline-form').attr('action')}/deadline`, {
data: JSON.stringify({
due_date: realDeadline
}),
headers: {
'X-Csrf-Token': csrf,
'X-Remote': true
},
contentType: 'application/json',
type: 'POST',
success() {
reload();
},
error() {
$('#deadline-loader').removeClass('loading');
$('#deadline-err-invalid-date').show();
}
});
};
window.deleteDependencyModal = function (id, type) {
$('.remove-dependency')
.modal({
closable: false,
duration: 200,
onApprove() {
$('#removeDependencyID').val(id);
$('#dependencyType').val(type);
$('#removeDependencyForm').trigger('submit');
}
})
.modal('show');
};
function initIssueList() {
const repolink = $('#repolink').val();
const repoId = $('#repoId').val();
const crossRepoSearch = $('#crossRepoSearch').val();
const tp = $('#type').val();
let issueSearchUrl = `${AppSubUrl}/api/v1/repos/${repolink}/issues?q={query}&type=${tp}`;
if (crossRepoSearch === 'true') {
issueSearchUrl = `${AppSubUrl}/api/v1/repos/issues/search?q={query}&priority_repo_id=${repoId}&type=${tp}`;
}
$('#new-dependency-drop-list').dropdown({
apiSettings: {
url: issueSearchUrl,
onResponse(response) {
const filteredResponse = {success: true, results: []};
const currIssueId = $('#new-dependency-drop-list').data('issue-id');
// Parse the response from the api to work with our dropdown
$.each(response, (_i, issue) => {
// Don't list current issue in the dependency list.
if (issue.id === currIssueId) {
return;
}
filteredResponse.results.push({
name: `#${issue.number} ${htmlEncode(
issue.title
)} ${htmlEncode(
issue.repository.full_name
)} `,
value: issue.id
});
});
return filteredResponse;
},
cache: false
},
fullTextSearch: true
});
$('.menu a.label-filter-item').each(function () {
$(this).on('click', function (e) {
if (e.altKey) {
e.preventDefault();
const href = $(this).attr('href');
const id = $(this).data('label-id');
const regStr = `labels=(-?[0-9]+%2c)*(${id})(%2c-?[0-9]+)*&`;
const newStr = 'labels=$1-$2$3&';
window.location = href.replace(new RegExp(regStr), newStr);
}
});
});
$('.menu .ui.dropdown.label-filter').on('keydown', (e) => {
if (e.altKey && e.keyCode === 13) {
const selectedItems = $(
'.menu .ui.dropdown.label-filter .menu .item.selected'
);
if (selectedItems.length > 0) {
const item = $(selectedItems[0]);
const href = item.attr('href');
const id = item.data('label-id');
const regStr = `labels=(-?[0-9]+%2c)*(${id})(%2c-?[0-9]+)*&`;
const newStr = 'labels=$1-$2$3&';
window.location = href.replace(new RegExp(regStr), newStr);
}
}
});
}
window.cancelCodeComment = function (btn) {
const form = $(btn).closest('form');
if (form.length > 0 && form.hasClass('comment-form')) {
form.addClass('hide');
form
.parent()
.find('button.comment-form-reply')
.show();
} else {
form.closest('.comment-code-cloud').remove();
}
};
window.submitReply = function (btn) {
const form = $(btn).closest('form');
if (form.length > 0 && form.hasClass('comment-form')) {
form.trigger('submit');
}
};
window.onOAuthLoginClick = function () {
const oauthLoader = $('#oauth2-login-loader');
const oauthNav = $('#oauth2-login-navigator');
oauthNav.hide();
oauthLoader.removeClass('disabled');
setTimeout(() => {
// recover previous content to let user try again
// usually redirection will be performed before this action
oauthLoader.addClass('disabled');
oauthNav.show();
}, 5000);
};
// Pull SVGs via AJAX to workaround CORS issues with |