mirror of
https://github.com/go-gitea/gitea
synced 2024-09-25 21:26:03 +00:00
eb748f5f3c
This code adds a simple endpoint to apply patches to repositories and branches on gitea. This is then used along with the conflicting checking code in #18004 to provide a basic implementation of cherry-pick revert. Now because the buttons necessary for cherry-pick and revert have required us to create a dropdown next to the Browse Source button I've also implemented Create Branch and Create Tag operations. Fix #3880 Fix #17986 Signed-off-by: Andrew Thornton <art27@cantab.net>
218 lines
7.2 KiB
JavaScript
218 lines
7.2 KiB
JavaScript
import Vue from 'vue';
|
|
import $ from 'jquery';
|
|
import {vueDelimiters} from './VueComponentLoader.js';
|
|
|
|
export function initRepoBranchTagDropdown(selector) {
|
|
$(selector).each(function () {
|
|
const $dropdown = $(this);
|
|
const $data = $dropdown.find('.data');
|
|
const data = {
|
|
items: [],
|
|
mode: $data.data('mode'),
|
|
searchTerm: '',
|
|
refName: '',
|
|
noResults: '',
|
|
canCreateBranch: false,
|
|
menuVisible: false,
|
|
createTag: false,
|
|
isViewTag: false,
|
|
isViewBranch: false,
|
|
isViewTree: false,
|
|
active: 0,
|
|
branchForm: '',
|
|
branchURLPrefix: '',
|
|
branchURLSuffix: '',
|
|
tagURLPrefix: '',
|
|
tagURLSuffix: '',
|
|
setAction: false,
|
|
submitForm: false,
|
|
};
|
|
$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({
|
|
el: this,
|
|
delimiters: vueDelimiters,
|
|
data,
|
|
computed: {
|
|
filteredItems() {
|
|
const items = this.items.filter((item) => {
|
|
return ((this.mode === 'branches' && item.branch) || (this.mode === 'tags' && item.tag)) &&
|
|
(!this.searchTerm || item.name.toLowerCase().includes(this.searchTerm.toLowerCase()));
|
|
});
|
|
|
|
// no idea how to fix this so linting rule is disabled instead
|
|
this.active = (items.length === 0 && this.showCreateNewBranch ? 0 : -1); // eslint-disable-line vue/no-side-effects-in-computed-properties
|
|
return items;
|
|
},
|
|
showNoResults() {
|
|
return this.filteredItems.length === 0 && !this.showCreateNewBranch;
|
|
},
|
|
showCreateNewBranch() {
|
|
if (!this.canCreateBranch || !this.searchTerm) {
|
|
return false;
|
|
}
|
|
|
|
return this.items.filter((item) => item.name.toLowerCase() === this.searchTerm.toLowerCase()).length === 0;
|
|
}
|
|
},
|
|
|
|
watch: {
|
|
menuVisible(visible) {
|
|
if (visible) {
|
|
this.focusSearchField();
|
|
}
|
|
}
|
|
},
|
|
|
|
beforeMount() {
|
|
this.noResults = this.$el.getAttribute('data-no-results');
|
|
this.canCreateBranch = this.$el.getAttribute('data-can-create-branch') === 'true';
|
|
this.branchForm = this.$el.getAttribute('data-branch-form');
|
|
switch (this.$el.getAttribute('data-view-type')) {
|
|
case 'tree':
|
|
this.isViewTree = true;
|
|
break;
|
|
case 'tag':
|
|
this.isViewTag = true;
|
|
break;
|
|
default:
|
|
this.isViewBranch = true;
|
|
break;
|
|
}
|
|
this.refName = this.$el.getAttribute('data-ref-name');
|
|
this.branchURLPrefix = this.$el.getAttribute('data-branch-url-prefix');
|
|
this.branchURLSuffix = this.$el.getAttribute('data-branch-url-suffix');
|
|
this.tagURLPrefix = this.$el.getAttribute('data-tag-url-prefix');
|
|
this.tagURLSuffix = this.$el.getAttribute('data-tag-url-suffix');
|
|
this.setAction = this.$el.getAttribute('data-set-action') === 'true';
|
|
this.submitForm = this.$el.getAttribute('data-submit-form') === 'true';
|
|
|
|
|
|
document.body.addEventListener('click', (event) => {
|
|
if (this.$el.contains(event.target)) return;
|
|
if (this.menuVisible) {
|
|
Vue.set(this, 'menuVisible', false);
|
|
}
|
|
});
|
|
},
|
|
|
|
methods: {
|
|
selectItem(item) {
|
|
const prev = this.getSelected();
|
|
if (prev !== null) {
|
|
prev.selected = false;
|
|
}
|
|
item.selected = true;
|
|
const url = (item.tag) ? this.tagURLPrefix + item.url + this.tagURLSuffix : this.branchURLPrefix + item.url + this.branchURLSuffix;
|
|
if (this.branchForm === '') {
|
|
window.location.href = url;
|
|
} else {
|
|
this.isViewTree = false;
|
|
this.isViewTag = false;
|
|
this.isViewBranch = false;
|
|
this.$refs.dropdownRefName.textContent = item.name;
|
|
if (this.setAction) {
|
|
$(`#${this.branchForm}`).attr('action', url);
|
|
} else {
|
|
$(`#${this.branchForm} input[name="refURL"]`).val(url);
|
|
}
|
|
$(`#${this.branchForm} input[name="ref"]`).val(item.name);
|
|
if (item.tag) {
|
|
this.isViewTag = true;
|
|
$(`#${this.branchForm} input[name="refType"]`).val('tag');
|
|
} else {
|
|
this.isViewBranch = true;
|
|
$(`#${this.branchForm} input[name="refType"]`).val('branch');
|
|
}
|
|
if (this.submitForm) {
|
|
$(`#${this.branchForm}`).trigger('submit');
|
|
}
|
|
Vue.set(this, 'menuVisible', false);
|
|
}
|
|
},
|
|
createNewBranch() {
|
|
if (!this.showCreateNewBranch) return;
|
|
$(this.$refs.newBranchForm).trigger('submit');
|
|
},
|
|
focusSearchField() {
|
|
Vue.nextTick(() => {
|
|
this.$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) 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) {
|
|
if (event.keyCode === 40) { // arrow down
|
|
event.preventDefault();
|
|
|
|
if (this.active === -1) {
|
|
this.active = this.getSelectedIndexInFiltered();
|
|
}
|
|
|
|
if (this.active + (this.showCreateNewBranch ? 0 : 1) >= this.filteredItems.length) {
|
|
return;
|
|
}
|
|
this.active++;
|
|
this.scrollToActive();
|
|
} else if (event.keyCode === 38) { // arrow up
|
|
event.preventDefault();
|
|
|
|
if (this.active === -1) {
|
|
this.active = this.getSelectedIndexInFiltered();
|
|
}
|
|
|
|
if (this.active <= 0) {
|
|
return;
|
|
}
|
|
this.active--;
|
|
this.scrollToActive();
|
|
} else if (event.keyCode === 13) { // enter
|
|
event.preventDefault();
|
|
|
|
if (this.active >= this.filteredItems.length) {
|
|
this.createNewBranch();
|
|
} else if (this.active >= 0) {
|
|
this.selectItem(this.filteredItems[this.active]);
|
|
}
|
|
} else if (event.keyCode === 27) { // escape
|
|
event.preventDefault();
|
|
this.menuVisible = false;
|
|
}
|
|
}
|
|
}
|
|
});
|
|
});
|
|
}
|