Merge branch 'prettify-all-the-things-7' into 'master'
Prettify all the things (part 7) See merge request gitlab-org/gitlab-ce!22257
This commit is contained in:
commit
b0808af2d8
48 changed files with 810 additions and 663 deletions
|
@ -1,6 +1,6 @@
|
|||
import $ from 'jquery';
|
||||
|
||||
export const addTooltipToEl = (el) => {
|
||||
export const addTooltipToEl = el => {
|
||||
const textEl = el.querySelector('.js-breadcrumb-item-text');
|
||||
|
||||
if (textEl && textEl.scrollWidth > textEl.offsetWidth) {
|
||||
|
@ -14,17 +14,18 @@ export default () => {
|
|||
const breadcrumbs = document.querySelector('.js-breadcrumbs-list');
|
||||
|
||||
if (breadcrumbs) {
|
||||
const topLevelLinks = [...breadcrumbs.children].filter(el => !el.classList.contains('dropdown'))
|
||||
const topLevelLinks = [...breadcrumbs.children]
|
||||
.filter(el => !el.classList.contains('dropdown'))
|
||||
.map(el => el.querySelector('a'))
|
||||
.filter(el => el);
|
||||
const $expander = $('.js-breadcrumbs-collapsed-expander');
|
||||
|
||||
topLevelLinks.forEach(el => addTooltipToEl(el));
|
||||
|
||||
$expander.closest('.dropdown')
|
||||
.on('show.bs.dropdown hide.bs.dropdown', (e) => {
|
||||
$('.js-breadcrumbs-collapsed-expander', e.currentTarget).toggleClass('open')
|
||||
.tooltip('hide');
|
||||
});
|
||||
$expander.closest('.dropdown').on('show.bs.dropdown hide.bs.dropdown', e => {
|
||||
$('.js-breadcrumbs-collapsed-expander', e.currentTarget)
|
||||
.toggleClass('open')
|
||||
.tooltip('hide');
|
||||
});
|
||||
}
|
||||
};
|
||||
|
|
|
@ -12,16 +12,16 @@ export default class BuildArtifacts {
|
|||
}
|
||||
// eslint-disable-next-line class-methods-use-this
|
||||
disablePropagation() {
|
||||
$('.top-block').on('click', '.download', function (e) {
|
||||
$('.top-block').on('click', '.download', function(e) {
|
||||
return e.stopPropagation();
|
||||
});
|
||||
return $('.tree-holder').on('click', 'tr[data-link] a', function (e) {
|
||||
return $('.tree-holder').on('click', 'tr[data-link] a', function(e) {
|
||||
return e.stopImmediatePropagation();
|
||||
});
|
||||
}
|
||||
// eslint-disable-next-line class-methods-use-this
|
||||
setupEntryClick() {
|
||||
return $('.tree-holder').on('click', 'tr[data-link]', function () {
|
||||
return $('.tree-holder').on('click', 'tr[data-link]', function() {
|
||||
visitUrl(this.dataset.link, convertPermissionToBoolean(this.dataset.externalLink));
|
||||
});
|
||||
}
|
||||
|
@ -37,11 +37,15 @@ export default class BuildArtifacts {
|
|||
// We want the tooltip to show if you hover anywhere on the row
|
||||
// But be placed below and in the middle of the file name
|
||||
$('.js-artifact-tree-row')
|
||||
.on('mouseenter', (e) => {
|
||||
$(e.currentTarget).find('.js-artifact-tree-tooltip').tooltip('show');
|
||||
.on('mouseenter', e => {
|
||||
$(e.currentTarget)
|
||||
.find('.js-artifact-tree-tooltip')
|
||||
.tooltip('show');
|
||||
})
|
||||
.on('mouseleave', (e) => {
|
||||
$(e.currentTarget).find('.js-artifact-tree-tooltip').tooltip('hide');
|
||||
.on('mouseleave', e => {
|
||||
$(e.currentTarget)
|
||||
.find('.js-artifact-tree-tooltip')
|
||||
.tooltip('hide');
|
||||
});
|
||||
}
|
||||
}
|
||||
|
|
|
@ -7,11 +7,13 @@ import statusCodes from '../lib/utils/http_status';
|
|||
import VariableList from './ci_variable_list';
|
||||
|
||||
function generateErrorBoxContent(errors) {
|
||||
const errorList = [].concat(errors).map(errorString => `
|
||||
const errorList = [].concat(errors).map(
|
||||
errorString => `
|
||||
<li>
|
||||
${_.escape(errorString)}
|
||||
</li>
|
||||
`);
|
||||
`,
|
||||
);
|
||||
|
||||
return `
|
||||
<p>
|
||||
|
@ -25,13 +27,7 @@ function generateErrorBoxContent(errors) {
|
|||
|
||||
// Used for the variable list on CI/CD projects/groups settings page
|
||||
export default class AjaxVariableList {
|
||||
constructor({
|
||||
container,
|
||||
saveButton,
|
||||
errorBox,
|
||||
formField = 'variables',
|
||||
saveEndpoint,
|
||||
}) {
|
||||
constructor({ container, saveButton, errorBox, formField = 'variables', saveEndpoint }) {
|
||||
this.container = container;
|
||||
this.saveButton = saveButton;
|
||||
this.errorBox = errorBox;
|
||||
|
@ -58,18 +54,21 @@ export default class AjaxVariableList {
|
|||
// to match it up in `updateRowsWithPersistedVariables`
|
||||
this.variableList.toggleEnableRow(false);
|
||||
|
||||
return axios.patch(this.saveEndpoint, {
|
||||
variables_attributes: this.variableList.getAllData(),
|
||||
}, {
|
||||
// We want to be able to process the `res.data` from a 400 error response
|
||||
// and print the validation messages such as duplicate variable keys
|
||||
validateStatus: status => (
|
||||
status >= statusCodes.OK &&
|
||||
status < statusCodes.MULTIPLE_CHOICES
|
||||
) ||
|
||||
status === statusCodes.BAD_REQUEST,
|
||||
})
|
||||
.then((res) => {
|
||||
return axios
|
||||
.patch(
|
||||
this.saveEndpoint,
|
||||
{
|
||||
variables_attributes: this.variableList.getAllData(),
|
||||
},
|
||||
{
|
||||
// We want to be able to process the `res.data` from a 400 error response
|
||||
// and print the validation messages such as duplicate variable keys
|
||||
validateStatus: status =>
|
||||
(status >= statusCodes.OK && status < statusCodes.MULTIPLE_CHOICES) ||
|
||||
status === statusCodes.BAD_REQUEST,
|
||||
},
|
||||
)
|
||||
.then(res => {
|
||||
loadingIcon.classList.toggle('hide', true);
|
||||
this.variableList.toggleEnableRow(true);
|
||||
|
||||
|
@ -90,18 +89,21 @@ export default class AjaxVariableList {
|
|||
}
|
||||
|
||||
updateRowsWithPersistedVariables(persistedVariables = []) {
|
||||
const persistedVariableMap = [].concat(persistedVariables).reduce((variableMap, variable) => ({
|
||||
...variableMap,
|
||||
[variable.key]: variable,
|
||||
}), {});
|
||||
const persistedVariableMap = [].concat(persistedVariables).reduce(
|
||||
(variableMap, variable) => ({
|
||||
...variableMap,
|
||||
[variable.key]: variable,
|
||||
}),
|
||||
{},
|
||||
);
|
||||
|
||||
this.container.querySelectorAll('.js-row').forEach((row) => {
|
||||
this.container.querySelectorAll('.js-row').forEach(row => {
|
||||
// If we submitted a row that was destroyed, remove it so we don't try
|
||||
// to destroy it again which would cause a BE error
|
||||
const destroyInput = row.querySelector('.js-ci-variable-input-destroy');
|
||||
if (convertPermissionToBoolean(destroyInput.value)) {
|
||||
row.remove();
|
||||
// Update the ID input so any future edits and `_destroy` will apply on the BE
|
||||
// Update the ID input so any future edits and `_destroy` will apply on the BE
|
||||
} else {
|
||||
const key = row.querySelector('.js-ci-variable-input-key').value;
|
||||
const persistedVariable = persistedVariableMap[key];
|
||||
|
|
|
@ -16,10 +16,7 @@ function createEnvironmentItem(value) {
|
|||
}
|
||||
|
||||
export default class VariableList {
|
||||
constructor({
|
||||
container,
|
||||
formField,
|
||||
}) {
|
||||
constructor({ container, formField }) {
|
||||
this.$container = $(container);
|
||||
this.formField = formField;
|
||||
this.environmentDropdownMap = new WeakMap();
|
||||
|
@ -71,7 +68,7 @@ export default class VariableList {
|
|||
this.initRow(rowEl);
|
||||
});
|
||||
|
||||
this.$container.on('click', '.js-row-remove-button', (e) => {
|
||||
this.$container.on('click', '.js-row-remove-button', e => {
|
||||
e.preventDefault();
|
||||
this.removeRow($(e.currentTarget).closest('.js-row'));
|
||||
});
|
||||
|
@ -81,7 +78,7 @@ export default class VariableList {
|
|||
.join(',');
|
||||
|
||||
// Remove any empty rows except the last row
|
||||
this.$container.on('blur', inputSelector, (e) => {
|
||||
this.$container.on('blur', inputSelector, e => {
|
||||
const $row = $(e.currentTarget).closest('.js-row');
|
||||
|
||||
if ($row.is(':not(:last-child)') && !this.checkIfRowTouched($row)) {
|
||||
|
@ -136,7 +133,7 @@ export default class VariableList {
|
|||
$rowClone.removeAttr('data-is-persisted');
|
||||
|
||||
// Reset the inputs to their defaults
|
||||
Object.keys(this.inputMap).forEach((name) => {
|
||||
Object.keys(this.inputMap).forEach(name => {
|
||||
const entry = this.inputMap[name];
|
||||
$rowClone.find(entry.selector).val(entry.default);
|
||||
});
|
||||
|
@ -171,7 +168,7 @@ export default class VariableList {
|
|||
}
|
||||
|
||||
checkIfRowTouched($row) {
|
||||
return Object.keys(this.inputMap).some((name) => {
|
||||
return Object.keys(this.inputMap).some(name => {
|
||||
const entry = this.inputMap[name];
|
||||
const $el = $row.find(entry.selector);
|
||||
return $el.length && $el.val() !== entry.default;
|
||||
|
@ -190,11 +187,14 @@ export default class VariableList {
|
|||
getAllData() {
|
||||
// Ignore the last empty row because we don't want to try persist
|
||||
// a blank variable and run into validation problems.
|
||||
const validRows = this.$container.find('.js-row').toArray().slice(0, -1);
|
||||
const validRows = this.$container
|
||||
.find('.js-row')
|
||||
.toArray()
|
||||
.slice(0, -1);
|
||||
|
||||
return validRows.map((rowEl) => {
|
||||
return validRows.map(rowEl => {
|
||||
const resultant = {};
|
||||
Object.keys(this.inputMap).forEach((name) => {
|
||||
Object.keys(this.inputMap).forEach(name => {
|
||||
const entry = this.inputMap[name];
|
||||
const $input = $(rowEl).find(entry.selector);
|
||||
if ($input.length) {
|
||||
|
@ -207,11 +207,16 @@ export default class VariableList {
|
|||
}
|
||||
|
||||
getEnvironmentValues() {
|
||||
const valueMap = this.$container.find(this.inputMap.environment_scope.selector).toArray()
|
||||
.reduce((prevValueMap, envInput) => ({
|
||||
...prevValueMap,
|
||||
[envInput.value]: envInput.value,
|
||||
}), {});
|
||||
const valueMap = this.$container
|
||||
.find(this.inputMap.environment_scope.selector)
|
||||
.toArray()
|
||||
.reduce(
|
||||
(prevValueMap, envInput) => ({
|
||||
...prevValueMap,
|
||||
[envInput.value]: envInput.value,
|
||||
}),
|
||||
{},
|
||||
);
|
||||
|
||||
return Object.keys(valueMap).map(createEnvironmentItem);
|
||||
}
|
||||
|
|
|
@ -2,10 +2,7 @@ import $ from 'jquery';
|
|||
import VariableList from './ci_variable_list';
|
||||
|
||||
// Used for the variable list on scheduled pipeline edit page
|
||||
export default function setupNativeFormVariableList({
|
||||
container,
|
||||
formField = 'variables',
|
||||
}) {
|
||||
export default function setupNativeFormVariableList({ container, formField = 'variables' }) {
|
||||
const $container = $(container);
|
||||
|
||||
const variableList = new VariableList({
|
||||
|
|
|
@ -76,12 +76,8 @@ export default class ClusterStore {
|
|||
this.state.status = serverState.status;
|
||||
this.state.statusReason = serverState.status_reason;
|
||||
|
||||
serverState.applications.forEach((serverAppEntry) => {
|
||||
const {
|
||||
name: appId,
|
||||
status,
|
||||
status_reason: statusReason,
|
||||
} = serverAppEntry;
|
||||
serverState.applications.forEach(serverAppEntry => {
|
||||
const { name: appId, status, status_reason: statusReason } = serverAppEntry;
|
||||
|
||||
this.state.applications[appId] = {
|
||||
...(this.state.applications[appId] || {}),
|
||||
|
|
|
@ -24,36 +24,44 @@ class CommentTypeToggle {
|
|||
|
||||
setConfig() {
|
||||
const config = {
|
||||
InputSetter: [{
|
||||
input: this.noteTypeInput,
|
||||
valueAttribute: 'data-value',
|
||||
},
|
||||
{
|
||||
input: this.submitButton,
|
||||
valueAttribute: 'data-submit-text',
|
||||
}],
|
||||
InputSetter: [
|
||||
{
|
||||
input: this.noteTypeInput,
|
||||
valueAttribute: 'data-value',
|
||||
},
|
||||
{
|
||||
input: this.submitButton,
|
||||
valueAttribute: 'data-submit-text',
|
||||
},
|
||||
],
|
||||
};
|
||||
|
||||
if (this.closeButton) {
|
||||
config.InputSetter.push({
|
||||
input: this.closeButton,
|
||||
valueAttribute: 'data-close-text',
|
||||
}, {
|
||||
input: this.closeButton,
|
||||
valueAttribute: 'data-close-text',
|
||||
inputAttribute: 'data-alternative-text',
|
||||
});
|
||||
config.InputSetter.push(
|
||||
{
|
||||
input: this.closeButton,
|
||||
valueAttribute: 'data-close-text',
|
||||
},
|
||||
{
|
||||
input: this.closeButton,
|
||||
valueAttribute: 'data-close-text',
|
||||
inputAttribute: 'data-alternative-text',
|
||||
},
|
||||
);
|
||||
}
|
||||
|
||||
if (this.reopenButton) {
|
||||
config.InputSetter.push({
|
||||
input: this.reopenButton,
|
||||
valueAttribute: 'data-reopen-text',
|
||||
}, {
|
||||
input: this.reopenButton,
|
||||
valueAttribute: 'data-reopen-text',
|
||||
inputAttribute: 'data-alternative-text',
|
||||
});
|
||||
config.InputSetter.push(
|
||||
{
|
||||
input: this.reopenButton,
|
||||
valueAttribute: 'data-reopen-text',
|
||||
},
|
||||
{
|
||||
input: this.reopenButton,
|
||||
valueAttribute: 'data-reopen-text',
|
||||
inputAttribute: 'data-alternative-text',
|
||||
},
|
||||
);
|
||||
}
|
||||
|
||||
return config;
|
||||
|
|
|
@ -9,44 +9,60 @@ const viewModes = ['two-up', 'swipe'];
|
|||
export default class ImageFile {
|
||||
constructor(file) {
|
||||
this.file = file;
|
||||
this.requestImageInfo($('.two-up.view .frame.deleted img', this.file), (function(_this) {
|
||||
return function(deletedWidth, deletedHeight) {
|
||||
return _this.requestImageInfo($('.two-up.view .frame.added img', _this.file), function(width, height) {
|
||||
_this.initViewModes();
|
||||
this.requestImageInfo(
|
||||
$('.two-up.view .frame.deleted img', this.file),
|
||||
(function(_this) {
|
||||
return function(deletedWidth, deletedHeight) {
|
||||
return _this.requestImageInfo($('.two-up.view .frame.added img', _this.file), function(
|
||||
width,
|
||||
height,
|
||||
) {
|
||||
_this.initViewModes();
|
||||
|
||||
// Load two-up view after images are loaded
|
||||
// so that we can display the correct width and height information
|
||||
const $images = $('.two-up.view img', _this.file);
|
||||
// Load two-up view after images are loaded
|
||||
// so that we can display the correct width and height information
|
||||
const $images = $('.two-up.view img', _this.file);
|
||||
|
||||
$images.waitForImages(function() {
|
||||
_this.initView('two-up');
|
||||
$images.waitForImages(function() {
|
||||
_this.initView('two-up');
|
||||
});
|
||||
});
|
||||
});
|
||||
};
|
||||
})(this));
|
||||
};
|
||||
})(this),
|
||||
);
|
||||
}
|
||||
|
||||
initViewModes() {
|
||||
const viewMode = viewModes[0];
|
||||
$('.view-modes', this.file).removeClass('hide');
|
||||
$('.view-modes-menu', this.file).on('click', 'li', (function(_this) {
|
||||
return function(event) {
|
||||
if (!$(event.currentTarget).hasClass('active')) {
|
||||
return _this.activateViewMode(event.currentTarget.className);
|
||||
}
|
||||
};
|
||||
})(this));
|
||||
$('.view-modes-menu', this.file).on(
|
||||
'click',
|
||||
'li',
|
||||
(function(_this) {
|
||||
return function(event) {
|
||||
if (!$(event.currentTarget).hasClass('active')) {
|
||||
return _this.activateViewMode(event.currentTarget.className);
|
||||
}
|
||||
};
|
||||
})(this),
|
||||
);
|
||||
return this.activateViewMode(viewMode);
|
||||
}
|
||||
|
||||
activateViewMode(viewMode) {
|
||||
$('.view-modes-menu li', this.file).removeClass('active').filter("." + viewMode).addClass('active');
|
||||
return $(".view:visible:not(." + viewMode + ")", this.file).fadeOut(200, (function(_this) {
|
||||
return function() {
|
||||
$(".view." + viewMode, _this.file).fadeIn(200);
|
||||
return _this.initView(viewMode);
|
||||
};
|
||||
})(this));
|
||||
$('.view-modes-menu li', this.file)
|
||||
.removeClass('active')
|
||||
.filter('.' + viewMode)
|
||||
.addClass('active');
|
||||
return $('.view:visible:not(.' + viewMode + ')', this.file).fadeOut(
|
||||
200,
|
||||
(function(_this) {
|
||||
return function() {
|
||||
$('.view.' + viewMode, _this.file).fadeIn(200);
|
||||
return _this.initView(viewMode);
|
||||
};
|
||||
})(this),
|
||||
);
|
||||
}
|
||||
|
||||
initView(viewMode) {
|
||||
|
@ -63,135 +79,154 @@ export default class ImageFile {
|
|||
$body.css('user-select', 'none');
|
||||
});
|
||||
|
||||
$body.off('mouseup').off('mousemove').on('mouseup', function() {
|
||||
dragging = false;
|
||||
$body.css('user-select', '');
|
||||
})
|
||||
.on('mousemove', function(e) {
|
||||
var left;
|
||||
if (!dragging) return;
|
||||
$body
|
||||
.off('mouseup')
|
||||
.off('mousemove')
|
||||
.on('mouseup', function() {
|
||||
dragging = false;
|
||||
$body.css('user-select', '');
|
||||
})
|
||||
.on('mousemove', function(e) {
|
||||
var left;
|
||||
if (!dragging) return;
|
||||
|
||||
left = e.pageX - ($offsetEl.offset().left + padding);
|
||||
left = e.pageX - ($offsetEl.offset().left + padding);
|
||||
|
||||
callback(e, left);
|
||||
});
|
||||
callback(e, left);
|
||||
});
|
||||
}
|
||||
|
||||
prepareFrames(view) {
|
||||
var maxHeight, maxWidth;
|
||||
maxWidth = 0;
|
||||
maxHeight = 0;
|
||||
$('.frame', view).each((function(_this) {
|
||||
return function(index, frame) {
|
||||
var height, width;
|
||||
width = $(frame).width();
|
||||
height = $(frame).height();
|
||||
maxWidth = width > maxWidth ? width : maxWidth;
|
||||
return maxHeight = height > maxHeight ? height : maxHeight;
|
||||
};
|
||||
})(this)).css({
|
||||
width: maxWidth,
|
||||
height: maxHeight
|
||||
});
|
||||
$('.frame', view)
|
||||
.each(
|
||||
(function(_this) {
|
||||
return function(index, frame) {
|
||||
var height, width;
|
||||
width = $(frame).width();
|
||||
height = $(frame).height();
|
||||
maxWidth = width > maxWidth ? width : maxWidth;
|
||||
return (maxHeight = height > maxHeight ? height : maxHeight);
|
||||
};
|
||||
})(this),
|
||||
)
|
||||
.css({
|
||||
width: maxWidth,
|
||||
height: maxHeight,
|
||||
});
|
||||
return [maxWidth, maxHeight];
|
||||
}
|
||||
|
||||
views = {
|
||||
'two-up': function() {
|
||||
return $('.two-up.view .wrap', this.file).each((function(_this) {
|
||||
return function(index, wrap) {
|
||||
$('img', wrap).each(function() {
|
||||
var currentWidth;
|
||||
currentWidth = $(this).width();
|
||||
if (currentWidth > availWidth / 2) {
|
||||
return $(this).width(availWidth / 2);
|
||||
}
|
||||
});
|
||||
return _this.requestImageInfo($('img', wrap), function(width, height) {
|
||||
$('.image-info .meta-width', wrap).text(width + "px");
|
||||
$('.image-info .meta-height', wrap).text(height + "px");
|
||||
return $('.image-info', wrap).removeClass('hide');
|
||||
});
|
||||
};
|
||||
})(this));
|
||||
return $('.two-up.view .wrap', this.file).each(
|
||||
(function(_this) {
|
||||
return function(index, wrap) {
|
||||
$('img', wrap).each(function() {
|
||||
var currentWidth;
|
||||
currentWidth = $(this).width();
|
||||
if (currentWidth > availWidth / 2) {
|
||||
return $(this).width(availWidth / 2);
|
||||
}
|
||||
});
|
||||
return _this.requestImageInfo($('img', wrap), function(width, height) {
|
||||
$('.image-info .meta-width', wrap).text(width + 'px');
|
||||
$('.image-info .meta-height', wrap).text(height + 'px');
|
||||
return $('.image-info', wrap).removeClass('hide');
|
||||
});
|
||||
};
|
||||
})(this),
|
||||
);
|
||||
},
|
||||
'swipe': function() {
|
||||
swipe() {
|
||||
var maxHeight, maxWidth;
|
||||
maxWidth = 0;
|
||||
maxHeight = 0;
|
||||
return $('.swipe.view', this.file).each((function(_this) {
|
||||
return function(index, view) {
|
||||
var $swipeWrap, $swipeBar, $swipeFrame, wrapPadding, ref;
|
||||
ref = _this.prepareFrames(view), [maxWidth, maxHeight] = ref;
|
||||
$swipeFrame = $('.swipe-frame', view);
|
||||
$swipeWrap = $('.swipe-wrap', view);
|
||||
$swipeBar = $('.swipe-bar', view);
|
||||
return $('.swipe.view', this.file).each(
|
||||
(function(_this) {
|
||||
return function(index, view) {
|
||||
var $swipeWrap, $swipeBar, $swipeFrame, wrapPadding, ref;
|
||||
(ref = _this.prepareFrames(view)), ([maxWidth, maxHeight] = ref);
|
||||
$swipeFrame = $('.swipe-frame', view);
|
||||
$swipeWrap = $('.swipe-wrap', view);
|
||||
$swipeBar = $('.swipe-bar', view);
|
||||
|
||||
$swipeFrame.css({
|
||||
width: maxWidth + 16,
|
||||
height: maxHeight + 28
|
||||
});
|
||||
$swipeWrap.css({
|
||||
width: maxWidth + 1,
|
||||
height: maxHeight + 2
|
||||
});
|
||||
// Set swipeBar left position to match image frame
|
||||
$swipeBar.css({
|
||||
left: 1
|
||||
});
|
||||
$swipeFrame.css({
|
||||
width: maxWidth + 16,
|
||||
height: maxHeight + 28,
|
||||
});
|
||||
$swipeWrap.css({
|
||||
width: maxWidth + 1,
|
||||
height: maxHeight + 2,
|
||||
});
|
||||
// Set swipeBar left position to match image frame
|
||||
$swipeBar.css({
|
||||
left: 1,
|
||||
});
|
||||
|
||||
wrapPadding = parseInt($swipeWrap.css('right').replace('px', ''), 10);
|
||||
wrapPadding = parseInt($swipeWrap.css('right').replace('px', ''), 10);
|
||||
|
||||
_this.initDraggable($swipeBar, wrapPadding, function(e, left) {
|
||||
if (left > 0 && left < $swipeFrame.width() - (wrapPadding * 2)) {
|
||||
$swipeWrap.width((maxWidth + 1) - left);
|
||||
$swipeBar.css('left', left);
|
||||
}
|
||||
});
|
||||
};
|
||||
})(this));
|
||||
_this.initDraggable($swipeBar, wrapPadding, function(e, left) {
|
||||
if (left > 0 && left < $swipeFrame.width() - wrapPadding * 2) {
|
||||
$swipeWrap.width(maxWidth + 1 - left);
|
||||
$swipeBar.css('left', left);
|
||||
}
|
||||
});
|
||||
};
|
||||
})(this),
|
||||
);
|
||||
},
|
||||
'onion-skin': function() {
|
||||
var dragTrackWidth, maxHeight, maxWidth;
|
||||
maxWidth = 0;
|
||||
maxHeight = 0;
|
||||
dragTrackWidth = $('.drag-track', this.file).width() - $('.dragger', this.file).width();
|
||||
return $('.onion-skin.view', this.file).each((function(_this) {
|
||||
return function(index, view) {
|
||||
var $frame, $track, $dragger, $frameAdded, framePadding, ref, dragging = false;
|
||||
ref = _this.prepareFrames(view), [maxWidth, maxHeight] = ref;
|
||||
$frame = $('.onion-skin-frame', view);
|
||||
$frameAdded = $('.frame.added', view);
|
||||
$track = $('.drag-track', view);
|
||||
$dragger = $('.dragger', $track);
|
||||
return $('.onion-skin.view', this.file).each(
|
||||
(function(_this) {
|
||||
return function(index, view) {
|
||||
var $frame,
|
||||
$track,
|
||||
$dragger,
|
||||
$frameAdded,
|
||||
framePadding,
|
||||
ref,
|
||||
dragging = false;
|
||||
(ref = _this.prepareFrames(view)), ([maxWidth, maxHeight] = ref);
|
||||
$frame = $('.onion-skin-frame', view);
|
||||
$frameAdded = $('.frame.added', view);
|
||||
$track = $('.drag-track', view);
|
||||
$dragger = $('.dragger', $track);
|
||||
|
||||
$frame.css({
|
||||
width: maxWidth + 16,
|
||||
height: maxHeight + 28
|
||||
});
|
||||
$('.swipe-wrap', view).css({
|
||||
width: maxWidth + 1,
|
||||
height: maxHeight + 2
|
||||
});
|
||||
$dragger.css({
|
||||
left: dragTrackWidth
|
||||
});
|
||||
$frame.css({
|
||||
width: maxWidth + 16,
|
||||
height: maxHeight + 28,
|
||||
});
|
||||
$('.swipe-wrap', view).css({
|
||||
width: maxWidth + 1,
|
||||
height: maxHeight + 2,
|
||||
});
|
||||
$dragger.css({
|
||||
left: dragTrackWidth,
|
||||
});
|
||||
|
||||
$frameAdded.css('opacity', 1);
|
||||
framePadding = parseInt($frameAdded.css('right').replace('px', ''), 10);
|
||||
$frameAdded.css('opacity', 1);
|
||||
framePadding = parseInt($frameAdded.css('right').replace('px', ''), 10);
|
||||
|
||||
_this.initDraggable($dragger, framePadding, function(e, left) {
|
||||
var opacity = left / dragTrackWidth;
|
||||
_this.initDraggable($dragger, framePadding, function(e, left) {
|
||||
var opacity = left / dragTrackWidth;
|
||||
|
||||
if (opacity >= 0 && opacity <= 1) {
|
||||
$dragger.css('left', left);
|
||||
$frameAdded.css('opacity', opacity);
|
||||
}
|
||||
});
|
||||
};
|
||||
})(this));
|
||||
}
|
||||
}
|
||||
if (opacity >= 0 && opacity <= 1) {
|
||||
$dragger.css('left', left);
|
||||
$frameAdded.css('opacity', opacity);
|
||||
}
|
||||
});
|
||||
};
|
||||
})(this),
|
||||
);
|
||||
},
|
||||
};
|
||||
|
||||
requestImageInfo(img, callback) {
|
||||
const domImg = img.get(0);
|
||||
|
@ -199,11 +234,14 @@ export default class ImageFile {
|
|||
if (domImg.complete) {
|
||||
return callback.call(this, domImg.naturalWidth, domImg.naturalHeight);
|
||||
} else {
|
||||
return img.on('load', (function(_this) {
|
||||
return function() {
|
||||
return callback.call(_this, domImg.naturalWidth, domImg.naturalHeight);
|
||||
};
|
||||
})(this));
|
||||
return img.on(
|
||||
'load',
|
||||
(function(_this) {
|
||||
return function() {
|
||||
return callback.call(_this, domImg.naturalWidth, domImg.naturalHeight);
|
||||
};
|
||||
})(this),
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -19,11 +19,13 @@ export default () => {
|
|||
const pipelineTableViewEl = document.querySelector('#commit-pipeline-table-view');
|
||||
|
||||
if (pipelineTableViewEl) {
|
||||
// Update MR and Commits tabs
|
||||
pipelineTableViewEl.addEventListener('update-pipelines-count', (event) => {
|
||||
if (event.detail.pipelines &&
|
||||
// Update MR and Commits tabs
|
||||
pipelineTableViewEl.addEventListener('update-pipelines-count', event => {
|
||||
if (
|
||||
event.detail.pipelines &&
|
||||
event.detail.pipelines.count &&
|
||||
event.detail.pipelines.count.all) {
|
||||
event.detail.pipelines.count.all
|
||||
) {
|
||||
const badge = document.querySelector('.js-pipelines-mr-count');
|
||||
|
||||
badge.textContent = event.detail.pipelines.count.all;
|
||||
|
|
|
@ -1,77 +1,73 @@
|
|||
<script>
|
||||
import PipelinesService from '../../pipelines/services/pipelines_service';
|
||||
import PipelineStore from '../../pipelines/stores/pipelines_store';
|
||||
import pipelinesMixin from '../../pipelines/mixins/pipelines';
|
||||
import PipelinesService from '../../pipelines/services/pipelines_service';
|
||||
import PipelineStore from '../../pipelines/stores/pipelines_store';
|
||||
import pipelinesMixin from '../../pipelines/mixins/pipelines';
|
||||
|
||||
export default {
|
||||
mixins: [
|
||||
pipelinesMixin,
|
||||
],
|
||||
props: {
|
||||
endpoint: {
|
||||
type: String,
|
||||
required: true,
|
||||
},
|
||||
helpPagePath: {
|
||||
type: String,
|
||||
required: true,
|
||||
},
|
||||
autoDevopsHelpPath: {
|
||||
type: String,
|
||||
required: true,
|
||||
},
|
||||
errorStateSvgPath: {
|
||||
type: String,
|
||||
required: true,
|
||||
},
|
||||
viewType: {
|
||||
type: String,
|
||||
required: false,
|
||||
default: 'child',
|
||||
},
|
||||
export default {
|
||||
mixins: [pipelinesMixin],
|
||||
props: {
|
||||
endpoint: {
|
||||
type: String,
|
||||
required: true,
|
||||
},
|
||||
|
||||
data() {
|
||||
const store = new PipelineStore();
|
||||
|
||||
return {
|
||||
store,
|
||||
state: store.state,
|
||||
};
|
||||
helpPagePath: {
|
||||
type: String,
|
||||
required: true,
|
||||
},
|
||||
|
||||
computed: {
|
||||
shouldRenderTable() {
|
||||
return !this.isLoading &&
|
||||
this.state.pipelines.length > 0 &&
|
||||
!this.hasError;
|
||||
},
|
||||
shouldRenderErrorState() {
|
||||
return this.hasError && !this.isLoading;
|
||||
},
|
||||
autoDevopsHelpPath: {
|
||||
type: String,
|
||||
required: true,
|
||||
},
|
||||
created() {
|
||||
this.service = new PipelinesService(this.endpoint);
|
||||
errorStateSvgPath: {
|
||||
type: String,
|
||||
required: true,
|
||||
},
|
||||
methods: {
|
||||
successCallback(resp) {
|
||||
// depending of the endpoint the response can either bring a `pipelines` key or not.
|
||||
const pipelines = resp.data.pipelines || resp.data;
|
||||
this.setCommonData(pipelines);
|
||||
|
||||
const updatePipelinesEvent = new CustomEvent('update-pipelines-count', {
|
||||
detail: {
|
||||
pipelines: resp.data,
|
||||
},
|
||||
});
|
||||
|
||||
// notifiy to update the count in tabs
|
||||
if (this.$el.parentElement) {
|
||||
this.$el.parentElement.dispatchEvent(updatePipelinesEvent);
|
||||
}
|
||||
},
|
||||
viewType: {
|
||||
type: String,
|
||||
required: false,
|
||||
default: 'child',
|
||||
},
|
||||
};
|
||||
},
|
||||
|
||||
data() {
|
||||
const store = new PipelineStore();
|
||||
|
||||
return {
|
||||
store,
|
||||
state: store.state,
|
||||
};
|
||||
},
|
||||
|
||||
computed: {
|
||||
shouldRenderTable() {
|
||||
return !this.isLoading && this.state.pipelines.length > 0 && !this.hasError;
|
||||
},
|
||||
shouldRenderErrorState() {
|
||||
return this.hasError && !this.isLoading;
|
||||
},
|
||||
},
|
||||
created() {
|
||||
this.service = new PipelinesService(this.endpoint);
|
||||
},
|
||||
methods: {
|
||||
successCallback(resp) {
|
||||
// depending of the endpoint the response can either bring a `pipelines` key or not.
|
||||
const pipelines = resp.data.pipelines || resp.data;
|
||||
this.setCommonData(pipelines);
|
||||
|
||||
const updatePipelinesEvent = new CustomEvent('update-pipelines-count', {
|
||||
detail: {
|
||||
pipelines: resp.data,
|
||||
},
|
||||
});
|
||||
|
||||
// notifiy to update the count in tabs
|
||||
if (this.$el.parentElement) {
|
||||
this.$el.parentElement.dispatchEvent(updatePipelinesEvent);
|
||||
}
|
||||
},
|
||||
},
|
||||
};
|
||||
</script>
|
||||
<template>
|
||||
<div class="content-list pipelines">
|
||||
|
|
|
@ -50,7 +50,7 @@ export function createContent(mergeRequests) {
|
|||
if (mergeRequests.length === 0) {
|
||||
$content.text(s__('Commits|No related merge requests found'));
|
||||
} else {
|
||||
mergeRequests.forEach((mergeRequest) => {
|
||||
mergeRequests.forEach(mergeRequest => {
|
||||
const $header = createHeader($content.children().length, mergeRequests.length);
|
||||
const $item = createItem(mergeRequest);
|
||||
$content.append($header);
|
||||
|
@ -64,8 +64,9 @@ export function createContent(mergeRequests) {
|
|||
export function fetchCommitMergeRequests() {
|
||||
const $container = $('.merge-requests');
|
||||
|
||||
axios.get($container.data('projectCommitPath'))
|
||||
.then((response) => {
|
||||
axios
|
||||
.get($container.data('projectCommitPath'))
|
||||
.then(response => {
|
||||
const $content = createContent(response.data);
|
||||
|
||||
$container.html($content);
|
||||
|
|
|
@ -32,22 +32,31 @@ export default class CommitsList {
|
|||
if (search === this.lastSearch) return Promise.resolve();
|
||||
const commitsUrl = `${form.attr('action')}?${form.serialize()}`;
|
||||
this.content.fadeTo('fast', 0.5);
|
||||
const params = form.serializeArray().reduce((acc, obj) => Object.assign(acc, {
|
||||
[obj.name]: obj.value,
|
||||
}), {});
|
||||
const params = form.serializeArray().reduce(
|
||||
(acc, obj) =>
|
||||
Object.assign(acc, {
|
||||
[obj.name]: obj.value,
|
||||
}),
|
||||
{},
|
||||
);
|
||||
|
||||
return axios.get(form.attr('action'), {
|
||||
params,
|
||||
})
|
||||
return axios
|
||||
.get(form.attr('action'), {
|
||||
params,
|
||||
})
|
||||
.then(({ data }) => {
|
||||
this.lastSearch = search;
|
||||
this.content.html(data.html);
|
||||
this.content.fadeTo('fast', 1.0);
|
||||
|
||||
// Change url so if user reload a page - search results are saved
|
||||
window.history.replaceState({
|
||||
page: commitsUrl,
|
||||
}, document.title, commitsUrl);
|
||||
window.history.replaceState(
|
||||
{
|
||||
page: commitsUrl,
|
||||
},
|
||||
document.title,
|
||||
commitsUrl,
|
||||
);
|
||||
})
|
||||
.catch(() => {
|
||||
this.content.fadeTo('fast', 1.0);
|
||||
|
@ -75,8 +84,15 @@ export default class CommitsList {
|
|||
processedData = $processedData.not(`li.js-commit-header[data-day='${loadedShownDayFirst}']`);
|
||||
|
||||
// Update commits count in the previous commits header.
|
||||
commitsCount += Number($(processedData).nextUntil('li.js-commit-header').first().find('li.commit').length);
|
||||
$commitsHeadersLast.find('span.commits-count').text(`${commitsCount} ${pluralize('commit', commitsCount)}`);
|
||||
commitsCount += Number(
|
||||
$(processedData)
|
||||
.nextUntil('li.js-commit-header')
|
||||
.first()
|
||||
.find('li.commit').length,
|
||||
);
|
||||
$commitsHeadersLast
|
||||
.find('span.commits-count')
|
||||
.text(`${commitsCount} ${pluralize('commit', commitsCount)}`);
|
||||
}
|
||||
|
||||
localTimeAgo($processedData.find('.js-timeago'));
|
||||
|
|
12
app/assets/javascripts/commons/bootstrap.js
vendored
12
app/assets/javascripts/commons/bootstrap.js
vendored
|
@ -5,6 +5,14 @@ import 'bootstrap';
|
|||
|
||||
// custom jQuery functions
|
||||
$.fn.extend({
|
||||
disable() { return $(this).prop('disabled', true).addClass('disabled'); },
|
||||
enable() { return $(this).prop('disabled', false).removeClass('disabled'); },
|
||||
disable() {
|
||||
return $(this)
|
||||
.prop('disabled', true)
|
||||
.addClass('disabled');
|
||||
},
|
||||
enable() {
|
||||
return $(this)
|
||||
.prop('disabled', false)
|
||||
.removeClass('disabled');
|
||||
},
|
||||
});
|
||||
|
|
|
@ -13,19 +13,23 @@ function openConfirmDangerModal($form, text) {
|
|||
$submit.disable();
|
||||
$input.focus();
|
||||
|
||||
$('.js-confirm-danger-input').off('input').on('input', function handleInput() {
|
||||
const confirmText = rstrip($(this).val());
|
||||
if (confirmText === confirmTextMatch) {
|
||||
$submit.enable();
|
||||
} else {
|
||||
$submit.disable();
|
||||
}
|
||||
});
|
||||
$('.js-confirm-danger-submit').off('click').on('click', () => $form.submit());
|
||||
$('.js-confirm-danger-input')
|
||||
.off('input')
|
||||
.on('input', function handleInput() {
|
||||
const confirmText = rstrip($(this).val());
|
||||
if (confirmText === confirmTextMatch) {
|
||||
$submit.enable();
|
||||
} else {
|
||||
$submit.disable();
|
||||
}
|
||||
});
|
||||
$('.js-confirm-danger-submit')
|
||||
.off('click')
|
||||
.on('click', () => $form.submit());
|
||||
}
|
||||
|
||||
export default function initConfirmDangerModal() {
|
||||
$(document).on('click', '.js-confirm-danger', (e) => {
|
||||
$(document).on('click', '.js-confirm-danger', e => {
|
||||
e.preventDefault();
|
||||
const $btn = $(e.target);
|
||||
const $form = $btn.closest('form');
|
||||
|
|
|
@ -20,8 +20,11 @@ export default class ContextualSidebar {
|
|||
}
|
||||
|
||||
bindEvents() {
|
||||
document.addEventListener('click', (e) => {
|
||||
if (!e.target.closest('.nav-sidebar') && (bp.getBreakpointSize() === 'sm' || bp.getBreakpointSize() === 'md')) {
|
||||
document.addEventListener('click', e => {
|
||||
if (
|
||||
!e.target.closest('.nav-sidebar') &&
|
||||
(bp.getBreakpointSize() === 'sm' || bp.getBreakpointSize() === 'md')
|
||||
) {
|
||||
this.toggleCollapsedSidebar(true);
|
||||
}
|
||||
});
|
||||
|
|
|
@ -36,7 +36,7 @@ export default class CreateItemDropdown {
|
|||
},
|
||||
selectable: true,
|
||||
toggleLabel(selected) {
|
||||
return (selected && 'id' in selected) ? _.escape(selected.title) : this.defaultToggleLabel;
|
||||
return selected && 'id' in selected ? _.escape(selected.title) : this.defaultToggleLabel;
|
||||
},
|
||||
fieldName: this.fieldName,
|
||||
text(item) {
|
||||
|
@ -46,7 +46,7 @@ export default class CreateItemDropdown {
|
|||
return _.escape(item.id);
|
||||
},
|
||||
onFilter: this.toggleCreateNewButton.bind(this),
|
||||
clicked: (options) => {
|
||||
clicked: options => {
|
||||
options.e.preventDefault();
|
||||
this.onSelect();
|
||||
},
|
||||
|
@ -77,9 +77,8 @@ export default class CreateItemDropdown {
|
|||
getData(term, callback) {
|
||||
this.getDataOption(term, (data = []) => {
|
||||
// Ensure the selected item isn't already in the data to avoid duplicates
|
||||
const alreadyHasSelectedItem = this.selectedItem && data.some(item =>
|
||||
item.id === this.selectedItem.id,
|
||||
);
|
||||
const alreadyHasSelectedItem =
|
||||
this.selectedItem && data.some(item => item.id === this.selectedItem.id);
|
||||
|
||||
let uniqueData = data;
|
||||
if (!alreadyHasSelectedItem) {
|
||||
|
@ -106,9 +105,7 @@ export default class CreateItemDropdown {
|
|||
if (newValue) {
|
||||
this.selectedItem = this.createNewItemFromValue(newValue);
|
||||
|
||||
this.$dropdownContainer
|
||||
.find('.js-dropdown-create-new-item code')
|
||||
.text(newValue);
|
||||
this.$dropdownContainer.find('.js-dropdown-create-new-item code').text(newValue);
|
||||
}
|
||||
|
||||
this.toggleFooter(!newValue);
|
||||
|
|
|
@ -37,7 +37,7 @@ export default class CreateLabelDropdown {
|
|||
addBinding() {
|
||||
const self = this;
|
||||
|
||||
this.$colorSuggestions.on('click', function (e) {
|
||||
this.$colorSuggestions.on('click', function(e) {
|
||||
const $this = $(this);
|
||||
self.addColorValue(e, $this);
|
||||
});
|
||||
|
@ -47,7 +47,7 @@ export default class CreateLabelDropdown {
|
|||
|
||||
this.$dropdownBack.on('click', this.resetForm.bind(this));
|
||||
|
||||
this.$cancelButton.on('click', function (e) {
|
||||
this.$cancelButton.on('click', function(e) {
|
||||
e.preventDefault();
|
||||
e.stopPropagation();
|
||||
|
||||
|
@ -79,13 +79,9 @@ export default class CreateLabelDropdown {
|
|||
}
|
||||
|
||||
resetForm() {
|
||||
this.$newLabelField
|
||||
.val('')
|
||||
.trigger('change');
|
||||
this.$newLabelField.val('').trigger('change');
|
||||
|
||||
this.$newColorField
|
||||
.val('')
|
||||
.trigger('change');
|
||||
this.$newColorField.val('').trigger('change');
|
||||
|
||||
this.$colorPreview
|
||||
.css('background-color', '')
|
||||
|
@ -97,31 +93,34 @@ export default class CreateLabelDropdown {
|
|||
e.preventDefault();
|
||||
e.stopPropagation();
|
||||
|
||||
Api.newLabel(this.namespacePath, this.projectPath, {
|
||||
title: this.$newLabelField.val(),
|
||||
color: this.$newColorField.val(),
|
||||
}, (label) => {
|
||||
this.$newLabelCreateButton.enable();
|
||||
Api.newLabel(
|
||||
this.namespacePath,
|
||||
this.projectPath,
|
||||
{
|
||||
title: this.$newLabelField.val(),
|
||||
color: this.$newColorField.val(),
|
||||
},
|
||||
label => {
|
||||
this.$newLabelCreateButton.enable();
|
||||
|
||||
if (label.message) {
|
||||
let errors;
|
||||
if (label.message) {
|
||||
let errors;
|
||||
|
||||
if (typeof label.message === 'string') {
|
||||
errors = label.message;
|
||||
if (typeof label.message === 'string') {
|
||||
errors = label.message;
|
||||
} else {
|
||||
errors = Object.keys(label.message)
|
||||
.map(key => `${humanize(key)} ${label.message[key].join(', ')}`)
|
||||
.join('<br/>');
|
||||
}
|
||||
|
||||
this.$newLabelError.html(errors).show();
|
||||
} else {
|
||||
errors = Object.keys(label.message).map(key =>
|
||||
`${humanize(key)} ${label.message[key].join(', ')}`,
|
||||
).join('<br/>');
|
||||
this.$dropdownBack.trigger('click');
|
||||
|
||||
$(document).trigger('created.label', label);
|
||||
}
|
||||
|
||||
this.$newLabelError
|
||||
.html(errors)
|
||||
.show();
|
||||
} else {
|
||||
this.$dropdownBack.trigger('click');
|
||||
|
||||
$(document).trigger('created.label', label);
|
||||
}
|
||||
});
|
||||
},
|
||||
);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -95,8 +95,10 @@ export default {
|
|||
.catch(() => new Flash(s__('DeployKeys|Error enabling deploy key')));
|
||||
},
|
||||
disableKey(deployKey, callback) {
|
||||
// eslint-disable-next-line no-alert
|
||||
if (window.confirm(s__('DeployKeys|You are going to remove this deploy key. Are you sure?'))) {
|
||||
if (
|
||||
// eslint-disable-next-line no-alert
|
||||
window.confirm(s__('DeployKeys|You are going to remove this deploy key. Are you sure?'))
|
||||
) {
|
||||
this.service
|
||||
.disableKey(deployKey.id)
|
||||
.then(this.fetchKeys)
|
||||
|
|
|
@ -8,17 +8,14 @@ export default class DeployKeysService {
|
|||
}
|
||||
|
||||
getKeys() {
|
||||
return this.axios.get()
|
||||
.then(response => response.data);
|
||||
return this.axios.get().then(response => response.data);
|
||||
}
|
||||
|
||||
enableKey(id) {
|
||||
return this.axios.put(`${id}/enable`)
|
||||
.then(response => response.data);
|
||||
return this.axios.put(`${id}/enable`).then(response => response.data);
|
||||
}
|
||||
|
||||
disableKey(id) {
|
||||
return this.axios.put(`${id}/disable`)
|
||||
.then(response => response.data);
|
||||
return this.axios.put(`${id}/disable`).then(response => response.data);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -21,9 +21,12 @@ export default class Diff {
|
|||
});
|
||||
|
||||
const tab = document.getElementById('diffs');
|
||||
if (!tab || (tab && tab.dataset && tab.dataset.isLocked !== '')) FilesCommentButton.init($diffFile);
|
||||
if (!tab || (tab && tab.dataset && tab.dataset.isLocked !== ''))
|
||||
FilesCommentButton.init($diffFile);
|
||||
|
||||
const firstFile = $('.files').first().get(0);
|
||||
const firstFile = $('.files')
|
||||
.first()
|
||||
.get(0);
|
||||
const canCreateNote = firstFile && firstFile.hasAttribute('data-can-create-note');
|
||||
$diffFile.each((index, file) => imageDiffHelper.initImageDiff(file, canCreateNote));
|
||||
|
||||
|
@ -73,9 +76,10 @@ export default class Diff {
|
|||
const view = file.data('view');
|
||||
|
||||
const params = { since, to, bottom, offset, unfold, view };
|
||||
axios.get(link, { params })
|
||||
.then(({ data }) => $target.parent().replaceWith(data))
|
||||
.catch(() => flash(__('An error occurred while loading diff')));
|
||||
axios
|
||||
.get(link, { params })
|
||||
.then(({ data }) => $target.parent().replaceWith(data))
|
||||
.catch(() => flash(__('An error occurred while loading diff')));
|
||||
}
|
||||
|
||||
openAnchoredDiff(cb) {
|
||||
|
|
|
@ -136,7 +136,7 @@ export default function dropzoneInput(form) {
|
|||
|
||||
// removeAllFiles(true) stops uploading files (if any)
|
||||
// and remove them from dropzone files queue.
|
||||
$cancelButton.on('click', (e) => {
|
||||
$cancelButton.on('click', e => {
|
||||
e.preventDefault();
|
||||
e.stopPropagation();
|
||||
Dropzone.forElement($formDropzone.get(0)).removeAllFiles(true);
|
||||
|
@ -146,8 +146,10 @@ export default function dropzoneInput(form) {
|
|||
// clear dropzone files queue, change status of failed files to undefined,
|
||||
// and add that files to the dropzone files queue again.
|
||||
// addFile() adds file to dropzone files queue and upload it.
|
||||
$retryLink.on('click', (e) => {
|
||||
const dropzoneInstance = Dropzone.forElement(e.target.closest('.js-main-target-form').querySelector('.div-dropzone'));
|
||||
$retryLink.on('click', e => {
|
||||
const dropzoneInstance = Dropzone.forElement(
|
||||
e.target.closest('.js-main-target-form').querySelector('.div-dropzone'),
|
||||
);
|
||||
const failedFiles = dropzoneInstance.files;
|
||||
|
||||
e.preventDefault();
|
||||
|
@ -156,7 +158,7 @@ export default function dropzoneInput(form) {
|
|||
// uploading of files that are being uploaded at the moment.
|
||||
dropzoneInstance.removeAllFiles(true);
|
||||
|
||||
failedFiles.map((failedFile) => {
|
||||
failedFiles.map(failedFile => {
|
||||
const file = failedFile;
|
||||
|
||||
if (file.status === Dropzone.ERROR) {
|
||||
|
@ -168,7 +170,7 @@ export default function dropzoneInput(form) {
|
|||
});
|
||||
});
|
||||
// eslint-disable-next-line consistent-return
|
||||
handlePaste = (event) => {
|
||||
handlePaste = event => {
|
||||
const pasteEvent = event.originalEvent;
|
||||
if (pasteEvent.clipboardData && pasteEvent.clipboardData.items) {
|
||||
const image = isImage(pasteEvent);
|
||||
|
@ -182,7 +184,7 @@ export default function dropzoneInput(form) {
|
|||
}
|
||||
};
|
||||
|
||||
isImage = (data) => {
|
||||
isImage = data => {
|
||||
let i = 0;
|
||||
while (i < data.clipboardData.items.length) {
|
||||
const item = data.clipboardData.items[i];
|
||||
|
@ -203,8 +205,12 @@ export default function dropzoneInput(form) {
|
|||
const caretStart = textarea.selectionStart;
|
||||
const caretEnd = textarea.selectionEnd;
|
||||
const textEnd = $(child).val().length;
|
||||
const beforeSelection = $(child).val().substring(0, caretStart);
|
||||
const afterSelection = $(child).val().substring(caretEnd, textEnd);
|
||||
const beforeSelection = $(child)
|
||||
.val()
|
||||
.substring(0, caretStart);
|
||||
const afterSelection = $(child)
|
||||
.val()
|
||||
.substring(caretEnd, textEnd);
|
||||
$(child).val(beforeSelection + formattedText + afterSelection);
|
||||
textarea.setSelectionRange(caretStart + formattedText.length, caretEnd + formattedText.length);
|
||||
textarea.style.height = `${textarea.scrollHeight}px`;
|
||||
|
@ -212,11 +218,11 @@ export default function dropzoneInput(form) {
|
|||
return formTextarea.trigger('input');
|
||||
};
|
||||
|
||||
addFileToForm = (path) => {
|
||||
addFileToForm = path => {
|
||||
$(form).append(`<input type="hidden" name="files[]" value="${_.escape(path)}">`);
|
||||
};
|
||||
|
||||
getFilename = (e) => {
|
||||
getFilename = e => {
|
||||
let value;
|
||||
if (window.clipboardData && window.clipboardData.getData) {
|
||||
value = window.clipboardData.getData('Text');
|
||||
|
@ -231,7 +237,7 @@ export default function dropzoneInput(form) {
|
|||
|
||||
const closeSpinner = () => $uploadingProgressContainer.addClass('hide');
|
||||
|
||||
const showError = (message) => {
|
||||
const showError = message => {
|
||||
$uploadingErrorContainer.removeClass('hide');
|
||||
$uploadingErrorMessage.html(message);
|
||||
};
|
||||
|
@ -252,14 +258,15 @@ export default function dropzoneInput(form) {
|
|||
showSpinner();
|
||||
closeAlertMessage();
|
||||
|
||||
axios.post(uploadsPath, formData)
|
||||
axios
|
||||
.post(uploadsPath, formData)
|
||||
.then(({ data }) => {
|
||||
const md = data.link.markdown;
|
||||
|
||||
insertToTextArea(filename, md);
|
||||
closeSpinner();
|
||||
})
|
||||
.catch((e) => {
|
||||
.catch(e => {
|
||||
showError(e.response.data.message);
|
||||
closeSpinner();
|
||||
});
|
||||
|
@ -267,7 +274,8 @@ export default function dropzoneInput(form) {
|
|||
|
||||
updateAttachingMessage = (files, messageContainer) => {
|
||||
let attachingMessage;
|
||||
const filesCount = files.filter(file => file.status === 'uploading' || file.status === 'queued').length;
|
||||
const filesCount = files.filter(file => file.status === 'uploading' || file.status === 'queued')
|
||||
.length;
|
||||
|
||||
// Dinamycally change uploading files text depending on files number in
|
||||
// dropzone files queue.
|
||||
|
@ -282,7 +290,10 @@ export default function dropzoneInput(form) {
|
|||
|
||||
form.find('.markdown-selector').click(function onMarkdownClick(e) {
|
||||
e.preventDefault();
|
||||
$(this).closest('.gfm-form').find('.div-dropzone').click();
|
||||
$(this)
|
||||
.closest('.gfm-form')
|
||||
.find('.div-dropzone')
|
||||
.click();
|
||||
formTextarea.focus();
|
||||
});
|
||||
|
||||
|
|
|
@ -13,9 +13,11 @@ const rainbowCodePoint = 127752; // parseInt('1F308', 16)
|
|||
function isRainbowFlagEmoji(emojiUnicode) {
|
||||
const characters = Array.from(emojiUnicode);
|
||||
// Length 4 because flags are made of 2 characters which are surrogate pairs
|
||||
return emojiUnicode.length === 4 &&
|
||||
return (
|
||||
emojiUnicode.length === 4 &&
|
||||
characters[0].codePointAt(0) === baseFlagCodePoint &&
|
||||
characters[1].codePointAt(0) === rainbowCodePoint;
|
||||
characters[1].codePointAt(0) === rainbowCodePoint
|
||||
);
|
||||
}
|
||||
|
||||
// Chrome <57 renders keycaps oddly
|
||||
|
@ -26,22 +28,28 @@ function isKeycapEmoji(emojiUnicode) {
|
|||
}
|
||||
|
||||
// Check for a skin tone variation emoji which aren't always supported
|
||||
const tone1 = 127995;// parseInt('1F3FB', 16)
|
||||
const tone5 = 127999;// parseInt('1F3FF', 16)
|
||||
const tone1 = 127995; // parseInt('1F3FB', 16)
|
||||
const tone5 = 127999; // parseInt('1F3FF', 16)
|
||||
function isSkinToneComboEmoji(emojiUnicode) {
|
||||
return emojiUnicode.length > 2 && Array.from(emojiUnicode).some((char) => {
|
||||
const cp = char.codePointAt(0);
|
||||
return cp >= tone1 && cp <= tone5;
|
||||
});
|
||||
return (
|
||||
emojiUnicode.length > 2 &&
|
||||
Array.from(emojiUnicode).some(char => {
|
||||
const cp = char.codePointAt(0);
|
||||
return cp >= tone1 && cp <= tone5;
|
||||
})
|
||||
);
|
||||
}
|
||||
|
||||
// macOS supports most skin tone emoji's but
|
||||
// doesn't support the skin tone versions of horse racing
|
||||
const horseRacingCodePoint = 127943;// parseInt('1F3C7', 16)
|
||||
const horseRacingCodePoint = 127943; // parseInt('1F3C7', 16)
|
||||
function isHorceRacingSkinToneComboEmoji(emojiUnicode) {
|
||||
const firstCharacter = Array.from(emojiUnicode)[0];
|
||||
return firstCharacter && firstCharacter.codePointAt(0) === horseRacingCodePoint &&
|
||||
isSkinToneComboEmoji(emojiUnicode);
|
||||
return (
|
||||
firstCharacter &&
|
||||
firstCharacter.codePointAt(0) === horseRacingCodePoint &&
|
||||
isSkinToneComboEmoji(emojiUnicode)
|
||||
);
|
||||
}
|
||||
|
||||
// Check for `family_*`, `kiss_*`, `couple_*`
|
||||
|
@ -52,7 +60,7 @@ const personEndCodePoint = 128105; // parseInt('1F469', 16)
|
|||
function isPersonZwjEmoji(emojiUnicode) {
|
||||
let hasPersonEmoji = false;
|
||||
let hasZwj = false;
|
||||
Array.from(emojiUnicode).forEach((character) => {
|
||||
Array.from(emojiUnicode).forEach(character => {
|
||||
const cp = character.codePointAt(0);
|
||||
if (cp === zwj) {
|
||||
hasZwj = true;
|
||||
|
@ -80,10 +88,7 @@ function checkFlagEmojiSupport(unicodeSupportMap, emojiUnicode) {
|
|||
// in `isEmojiUnicodeSupported` logic
|
||||
function checkSkinToneModifierSupport(unicodeSupportMap, emojiUnicode) {
|
||||
const isSkinToneResult = isSkinToneComboEmoji(emojiUnicode);
|
||||
return (
|
||||
(unicodeSupportMap.skinToneModifier && isSkinToneResult) ||
|
||||
!isSkinToneResult
|
||||
);
|
||||
return (unicodeSupportMap.skinToneModifier && isSkinToneResult) || !isSkinToneResult;
|
||||
}
|
||||
|
||||
// Helper func so we don't have to run `isHorceRacingSkinToneComboEmoji` twice
|
||||
|
@ -91,8 +96,7 @@ function checkSkinToneModifierSupport(unicodeSupportMap, emojiUnicode) {
|
|||
function checkHorseRacingSkinToneComboEmojiSupport(unicodeSupportMap, emojiUnicode) {
|
||||
const isHorseRacingSkinToneResult = isHorceRacingSkinToneComboEmoji(emojiUnicode);
|
||||
return (
|
||||
(unicodeSupportMap.horseRacing && isHorseRacingSkinToneResult) ||
|
||||
!isHorseRacingSkinToneResult
|
||||
(unicodeSupportMap.horseRacing && isHorseRacingSkinToneResult) || !isHorseRacingSkinToneResult
|
||||
);
|
||||
}
|
||||
|
||||
|
@ -100,10 +104,7 @@ function checkHorseRacingSkinToneComboEmojiSupport(unicodeSupportMap, emojiUnico
|
|||
// in `isEmojiUnicodeSupported` logic
|
||||
function checkPersonEmojiSupport(unicodeSupportMap, emojiUnicode) {
|
||||
const isPersonZwjResult = isPersonZwjEmoji(emojiUnicode);
|
||||
return (
|
||||
(unicodeSupportMap.personZwj && isPersonZwjResult) ||
|
||||
!isPersonZwjResult
|
||||
);
|
||||
return (unicodeSupportMap.personZwj && isPersonZwjResult) || !isPersonZwjResult;
|
||||
}
|
||||
|
||||
// Takes in a support map and determines whether
|
||||
|
@ -111,16 +112,20 @@ function checkPersonEmojiSupport(unicodeSupportMap, emojiUnicode) {
|
|||
//
|
||||
// Combines all the edge case tests into a one-stop shop method
|
||||
function isEmojiUnicodeSupported(unicodeSupportMap = {}, emojiUnicode, unicodeVersion) {
|
||||
const isOlderThanChrome57 = unicodeSupportMap.meta && unicodeSupportMap.meta.isChrome &&
|
||||
const isOlderThanChrome57 =
|
||||
unicodeSupportMap.meta &&
|
||||
unicodeSupportMap.meta.isChrome &&
|
||||
unicodeSupportMap.meta.chromeVersion < 57;
|
||||
|
||||
// For comments about each scenario, see the comments above each individual respective function
|
||||
return unicodeSupportMap[unicodeVersion] &&
|
||||
return (
|
||||
unicodeSupportMap[unicodeVersion] &&
|
||||
!(isOlderThanChrome57 && isKeycapEmoji(emojiUnicode)) &&
|
||||
checkFlagEmojiSupport(unicodeSupportMap, emojiUnicode) &&
|
||||
checkSkinToneModifierSupport(unicodeSupportMap, emojiUnicode) &&
|
||||
checkHorseRacingSkinToneComboEmojiSupport(unicodeSupportMap, emojiUnicode) &&
|
||||
checkPersonEmojiSupport(unicodeSupportMap, emojiUnicode);
|
||||
checkPersonEmojiSupport(unicodeSupportMap, emojiUnicode)
|
||||
);
|
||||
}
|
||||
|
||||
export {
|
||||
|
|
|
@ -2,7 +2,7 @@ import $ from 'jquery';
|
|||
import Cookies from 'js-cookie';
|
||||
|
||||
export default () => {
|
||||
$('.js-experiment-feature-toggle').on('change', (e) => {
|
||||
$('.js-experiment-feature-toggle').on('change', e => {
|
||||
const el = e.target;
|
||||
|
||||
Cookies.set(el.name, el.value, {
|
||||
|
|
|
@ -25,13 +25,15 @@ export default {
|
|||
|
||||
if (!this.userCanCreateNote) {
|
||||
// data-can-create-note is an empty string when true, otherwise undefined
|
||||
this.userCanCreateNote = $diffFile.closest(DIFF_CONTAINER_SELECTOR).data('canCreateNote') === '';
|
||||
this.userCanCreateNote =
|
||||
$diffFile.closest(DIFF_CONTAINER_SELECTOR).data('canCreateNote') === '';
|
||||
}
|
||||
|
||||
this.isParallelView = Cookies.get('diff_view') === 'parallel';
|
||||
|
||||
if (this.userCanCreateNote) {
|
||||
$diffFile.on('mouseover', LINE_COLUMN_CLASSES, e => this.showButton(this.isParallelView, e))
|
||||
$diffFile
|
||||
.on('mouseover', LINE_COLUMN_CLASSES, e => this.showButton(this.isParallelView, e))
|
||||
.on('mouseleave', LINE_COLUMN_CLASSES, e => this.hideButton(this.isParallelView, e));
|
||||
}
|
||||
},
|
||||
|
@ -64,9 +66,11 @@ export default {
|
|||
},
|
||||
|
||||
validateButtonParent(buttonParentElement) {
|
||||
return !buttonParentElement.classList.contains(EMPTY_CELL_CLASS) &&
|
||||
return (
|
||||
!buttonParentElement.classList.contains(EMPTY_CELL_CLASS) &&
|
||||
!buttonParentElement.classList.contains(UNFOLDABLE_LINE_CLASS) &&
|
||||
!buttonParentElement.classList.contains(NO_COMMENT_CLASS) &&
|
||||
!buttonParentElement.parentNode.classList.contains(DIFF_EXPANDED_CLASS);
|
||||
!buttonParentElement.parentNode.classList.contains(DIFF_EXPANDED_CLASS)
|
||||
);
|
||||
},
|
||||
};
|
||||
|
|
|
@ -65,12 +65,15 @@ export default class FilterableList {
|
|||
|
||||
this.isBusy = true;
|
||||
|
||||
return axios.get(this.getFilterEndpoint(), {
|
||||
params,
|
||||
}).then((res) => {
|
||||
this.onFilterSuccess(res, params);
|
||||
this.onFilterComplete();
|
||||
}).catch(() => this.onFilterComplete());
|
||||
return axios
|
||||
.get(this.getFilterEndpoint(), {
|
||||
params,
|
||||
})
|
||||
.then(res => {
|
||||
this.onFilterSuccess(res, params);
|
||||
this.onFilterComplete();
|
||||
})
|
||||
.catch(() => this.onFilterComplete());
|
||||
}
|
||||
|
||||
onFilterSuccess(response, queryData) {
|
||||
|
@ -81,9 +84,13 @@ export default class FilterableList {
|
|||
// Change url so if user reload a page - search results are saved
|
||||
const currentPath = this.getPagePath(queryData);
|
||||
|
||||
return window.history.replaceState({
|
||||
page: currentPath,
|
||||
}, document.title, currentPath);
|
||||
return window.history.replaceState(
|
||||
{
|
||||
page: currentPath,
|
||||
},
|
||||
document.title,
|
||||
currentPath,
|
||||
);
|
||||
}
|
||||
|
||||
onFilterComplete() {
|
||||
|
|
|
@ -8,14 +8,19 @@ const hideFlash = (flashEl, fadeTransition = true) => {
|
|||
});
|
||||
}
|
||||
|
||||
flashEl.addEventListener('transitionend', () => {
|
||||
flashEl.remove();
|
||||
window.dispatchEvent(new Event('resize'));
|
||||
if (document.body.classList.contains('flash-shown')) document.body.classList.remove('flash-shown');
|
||||
}, {
|
||||
once: true,
|
||||
passive: true,
|
||||
});
|
||||
flashEl.addEventListener(
|
||||
'transitionend',
|
||||
() => {
|
||||
flashEl.remove();
|
||||
window.dispatchEvent(new Event('resize'));
|
||||
if (document.body.classList.contains('flash-shown'))
|
||||
document.body.classList.remove('flash-shown');
|
||||
},
|
||||
{
|
||||
once: true,
|
||||
passive: true,
|
||||
},
|
||||
);
|
||||
|
||||
if (!fadeTransition) flashEl.dispatchEvent(new Event('transitionend'));
|
||||
};
|
||||
|
@ -84,7 +89,9 @@ const createFlash = function createFlash(
|
|||
flashEl.innerHTML += createAction(actionConfig);
|
||||
|
||||
if (actionConfig.clickHandler) {
|
||||
flashEl.querySelector('.flash-action').addEventListener('click', e => actionConfig.clickHandler(e));
|
||||
flashEl
|
||||
.querySelector('.flash-action')
|
||||
.addEventListener('click', e => actionConfig.clickHandler(e));
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -95,11 +102,5 @@ const createFlash = function createFlash(
|
|||
return flashContainer;
|
||||
};
|
||||
|
||||
export {
|
||||
createFlash as default,
|
||||
createFlashEl,
|
||||
createAction,
|
||||
hideFlash,
|
||||
removeFlashClickListener,
|
||||
};
|
||||
export { createFlash as default, createFlashEl, createAction, hideFlash, removeFlashClickListener };
|
||||
window.Flash = createFlash;
|
||||
|
|
|
@ -11,9 +11,13 @@ let sidebar;
|
|||
|
||||
export const mousePos = [];
|
||||
|
||||
export const setSidebar = (el) => { sidebar = el; };
|
||||
export const setSidebar = el => {
|
||||
sidebar = el;
|
||||
};
|
||||
export const getOpenMenu = () => currentOpenMenu;
|
||||
export const setOpenMenu = (menu = null) => { currentOpenMenu = menu; };
|
||||
export const setOpenMenu = (menu = null) => {
|
||||
currentOpenMenu = menu;
|
||||
};
|
||||
|
||||
export const slope = (a, b) => (b.y - a.y) / (b.x - a.x);
|
||||
|
||||
|
@ -21,9 +25,10 @@ let headerHeight = 50;
|
|||
|
||||
export const getHeaderHeight = () => headerHeight;
|
||||
|
||||
export const isSidebarCollapsed = () => sidebar && sidebar.classList.contains('sidebar-collapsed-desktop');
|
||||
export const isSidebarCollapsed = () =>
|
||||
sidebar && sidebar.classList.contains('sidebar-collapsed-desktop');
|
||||
|
||||
export const canShowActiveSubItems = (el) => {
|
||||
export const canShowActiveSubItems = el => {
|
||||
if (el.classList.contains('active') && !isSidebarCollapsed()) {
|
||||
return false;
|
||||
}
|
||||
|
@ -31,7 +36,10 @@ export const canShowActiveSubItems = (el) => {
|
|||
return true;
|
||||
};
|
||||
|
||||
export const canShowSubItems = () => bp.getBreakpointSize() === 'sm' || bp.getBreakpointSize() === 'md' || bp.getBreakpointSize() === 'lg';
|
||||
export const canShowSubItems = () =>
|
||||
bp.getBreakpointSize() === 'sm' ||
|
||||
bp.getBreakpointSize() === 'md' ||
|
||||
bp.getBreakpointSize() === 'lg';
|
||||
|
||||
export const getHideSubItemsInterval = () => {
|
||||
if (!currentOpenMenu || !mousePos.length) return 0;
|
||||
|
@ -41,11 +49,12 @@ export const getHideSubItemsInterval = () => {
|
|||
const currentMousePosY = currentMousePos.y;
|
||||
const [menuTop, menuBottom] = menuCornerLocs;
|
||||
|
||||
if (currentMousePosY < menuTop.y ||
|
||||
currentMousePosY > menuBottom.y) return 0;
|
||||
if (currentMousePosY < menuTop.y || currentMousePosY > menuBottom.y) return 0;
|
||||
|
||||
if (slope(prevMousePos, menuBottom) < slope(currentMousePos, menuBottom) &&
|
||||
slope(prevMousePos, menuTop) > slope(currentMousePos, menuTop)) {
|
||||
if (
|
||||
slope(prevMousePos, menuBottom) < slope(currentMousePos, menuBottom) &&
|
||||
slope(prevMousePos, menuTop) > slope(currentMousePos, menuTop)
|
||||
) {
|
||||
return HIDE_INTERVAL_TIMEOUT;
|
||||
}
|
||||
|
||||
|
@ -56,11 +65,12 @@ export const calculateTop = (boundingRect, outerHeight) => {
|
|||
const windowHeight = window.innerHeight;
|
||||
const bottomOverflow = windowHeight - (boundingRect.top + outerHeight);
|
||||
|
||||
return bottomOverflow < 0 ? (boundingRect.top - outerHeight) + boundingRect.height :
|
||||
boundingRect.top;
|
||||
return bottomOverflow < 0
|
||||
? boundingRect.top - outerHeight + boundingRect.height
|
||||
: boundingRect.top;
|
||||
};
|
||||
|
||||
export const hideMenu = (el) => {
|
||||
export const hideMenu = el => {
|
||||
if (!el) return;
|
||||
|
||||
const parentEl = el.parentNode;
|
||||
|
@ -101,7 +111,7 @@ export const moveSubItemsToPosition = (el, subItems) => {
|
|||
}
|
||||
};
|
||||
|
||||
export const showSubLevelItems = (el) => {
|
||||
export const showSubLevelItems = el => {
|
||||
const subItems = el.querySelector('.sidebar-sub-level-items');
|
||||
const isIconOnly = subItems && subItems.classList.contains('is-fly-out-only');
|
||||
|
||||
|
@ -128,16 +138,20 @@ export const mouseEnterTopItems = (el, timeout = getHideSubItemsInterval()) => {
|
|||
}, timeout);
|
||||
};
|
||||
|
||||
export const mouseLeaveTopItem = (el) => {
|
||||
export const mouseLeaveTopItem = el => {
|
||||
const subItems = el.querySelector('.sidebar-sub-level-items');
|
||||
|
||||
if (!canShowSubItems() || !canShowActiveSubItems(el) ||
|
||||
(subItems && subItems === currentOpenMenu)) return;
|
||||
if (
|
||||
!canShowSubItems() ||
|
||||
!canShowActiveSubItems(el) ||
|
||||
(subItems && subItems === currentOpenMenu)
|
||||
)
|
||||
return;
|
||||
|
||||
el.classList.remove(IS_OVER_CLASS);
|
||||
};
|
||||
|
||||
export const documentMouseMove = (e) => {
|
||||
export const documentMouseMove = e => {
|
||||
mousePos.push({
|
||||
x: e.clientX,
|
||||
y: e.clientY,
|
||||
|
@ -146,7 +160,7 @@ export const documentMouseMove = (e) => {
|
|||
if (mousePos.length > 6) mousePos.shift();
|
||||
};
|
||||
|
||||
export const subItemsMouseLeave = (relatedTarget) => {
|
||||
export const subItemsMouseLeave = relatedTarget => {
|
||||
clearTimeout(timeoutId);
|
||||
|
||||
if (relatedTarget && !relatedTarget.closest(`.${IS_OVER_CLASS}`)) {
|
||||
|
@ -174,7 +188,7 @@ export default () => {
|
|||
|
||||
headerHeight = document.querySelector('.nav-sidebar').offsetTop;
|
||||
|
||||
items.forEach((el) => {
|
||||
items.forEach(el => {
|
||||
const subItems = el.querySelector('.sidebar-sub-level-items');
|
||||
|
||||
if (subItems) {
|
||||
|
|
|
@ -116,7 +116,8 @@ export default class GlFieldError {
|
|||
this.form.focusOnFirstInvalid.apply(this.form);
|
||||
|
||||
// For UX, wait til after first invalid submission to check each keyup
|
||||
this.inputElement.off('keyup.fieldValidator')
|
||||
this.inputElement
|
||||
.off('keyup.fieldValidator')
|
||||
.on('keyup.fieldValidator', this.updateValidity.bind(this));
|
||||
}
|
||||
|
||||
|
|
|
@ -16,9 +16,12 @@ export default class GlFieldErrors {
|
|||
initValidators() {
|
||||
// register selectors here as needed
|
||||
const validateSelectors = [':text', ':password', '[type=email]']
|
||||
.map(selector => `input${selector}`).join(',');
|
||||
.map(selector => `input${selector}`)
|
||||
.join(',');
|
||||
|
||||
this.state.inputs = this.form.find(validateSelectors).toArray()
|
||||
this.state.inputs = this.form
|
||||
.find(validateSelectors)
|
||||
.toArray()
|
||||
.filter(input => !input.classList.contains(customValidationFlag))
|
||||
.map(input => new GlFieldError({ input, formErrors: this }));
|
||||
|
||||
|
@ -42,7 +45,7 @@ export default class GlFieldErrors {
|
|||
|
||||
/* Public method for triggering validity updates manually */
|
||||
updateFormValidityState() {
|
||||
this.state.inputs.forEach((field) => {
|
||||
this.state.inputs.forEach(field => {
|
||||
if (field.state.submitted) {
|
||||
field.updateValidity();
|
||||
}
|
||||
|
@ -50,8 +53,9 @@ export default class GlFieldErrors {
|
|||
}
|
||||
|
||||
focusOnFirstInvalid() {
|
||||
const firstInvalid = this.state.inputs
|
||||
.filter(input => !input.inputDomElement.validity.valid)[0];
|
||||
const firstInvalid = this.state.inputs.filter(
|
||||
input => !input.inputDomElement.validity.valid,
|
||||
)[0];
|
||||
firstInvalid.inputElement.focus();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -39,7 +39,10 @@ export default class GLForm {
|
|||
this.form.find('.div-dropzone').remove();
|
||||
this.form.addClass('gfm-form');
|
||||
// remove notify commit author checkbox for non-commit notes
|
||||
gl.utils.disableButtonIfEmptyField(this.form.find('.js-note-text'), this.form.find('.js-comment-button, .js-note-new-discussion'));
|
||||
gl.utils.disableButtonIfEmptyField(
|
||||
this.form.find('.js-note-text'),
|
||||
this.form.find('.js-comment-button, .js-note-new-discussion'),
|
||||
);
|
||||
this.autoComplete = new GfmAutoComplete(gl.GfmAutoComplete && gl.GfmAutoComplete.dataSources);
|
||||
this.autoComplete.setup(this.form.find('.js-gfm-input'), this.enableGFM);
|
||||
dropzoneInput(this.form);
|
||||
|
@ -55,11 +58,9 @@ export default class GLForm {
|
|||
}
|
||||
|
||||
setupAutosize() {
|
||||
this.textarea.off('autosize:resized')
|
||||
.on('autosize:resized', this.setHeightData.bind(this));
|
||||
this.textarea.off('autosize:resized').on('autosize:resized', this.setHeightData.bind(this));
|
||||
|
||||
this.textarea.off('mouseup.autosize')
|
||||
.on('mouseup.autosize', this.destroyAutosize.bind(this));
|
||||
this.textarea.off('mouseup.autosize').on('mouseup.autosize', this.destroyAutosize.bind(this));
|
||||
|
||||
setTimeout(() => {
|
||||
autosize(this.textarea);
|
||||
|
@ -91,10 +92,14 @@ export default class GLForm {
|
|||
|
||||
addEventListeners() {
|
||||
this.textarea.on('focus', function focusTextArea() {
|
||||
$(this).closest('.md-area').addClass('is-focused');
|
||||
$(this)
|
||||
.closest('.md-area')
|
||||
.addClass('is-focused');
|
||||
});
|
||||
this.textarea.on('blur', function blurTextArea() {
|
||||
$(this).closest('.md-area').removeClass('is-focused');
|
||||
$(this)
|
||||
.closest('.md-area')
|
||||
.removeClass('is-focused');
|
||||
});
|
||||
}
|
||||
}
|
||||
|
|
|
@ -7,8 +7,9 @@ export default function groupAvatar() {
|
|||
});
|
||||
$('.js-group-avatar-input').on('change', function onChangeAvatarInput() {
|
||||
const form = $(this).closest('form');
|
||||
// eslint-disable-next-line no-useless-escape
|
||||
const filename = $(this).val().replace(/^.*[\\\/]/, '');
|
||||
const filename = $(this)
|
||||
.val()
|
||||
.replace(/^.*[\\\/]/, ''); // eslint-disable-line no-useless-escape
|
||||
return form.find('.js-avatar-filename').text(filename);
|
||||
});
|
||||
}
|
||||
|
|
|
@ -23,7 +23,8 @@ export default class GroupLabelSubscription {
|
|||
event.preventDefault();
|
||||
|
||||
const url = this.$unsubscribeButtons.attr('data-url');
|
||||
axios.post(url)
|
||||
axios
|
||||
.post(url)
|
||||
.then(() => {
|
||||
this.toggleSubscriptionButtons();
|
||||
this.$unsubscribeButtons.removeAttr('data-url');
|
||||
|
@ -39,7 +40,8 @@ export default class GroupLabelSubscription {
|
|||
|
||||
this.$unsubscribeButtons.attr('data-url', url);
|
||||
|
||||
axios.post(url)
|
||||
axios
|
||||
.post(url)
|
||||
.then(() => GroupLabelSubscription.setNewTooltip($btn))
|
||||
.then(() => this.toggleSubscriptionButtons())
|
||||
.catch(() => flash(__('There was an error when subscribing to this label.')));
|
||||
|
@ -58,6 +60,8 @@ export default class GroupLabelSubscription {
|
|||
const newTitle = tooltipTitles[type];
|
||||
|
||||
$('.js-unsubscribe-button', $button.closest('.label-actions-list'))
|
||||
.tooltip('hide').attr('title', newTitle).tooltip('_fixTitle');
|
||||
.tooltip('hide')
|
||||
.attr('title', newTitle)
|
||||
.tooltip('_fixTitle');
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,44 +1,44 @@
|
|||
<script>
|
||||
import icon from '~/vue_shared/components/icon.vue';
|
||||
import timeAgoTooltip from '~/vue_shared/components/time_ago_tooltip.vue';
|
||||
import {
|
||||
ITEM_TYPE,
|
||||
VISIBILITY_TYPE_ICON,
|
||||
GROUP_VISIBILITY_TYPE,
|
||||
PROJECT_VISIBILITY_TYPE,
|
||||
} from '../constants';
|
||||
import itemStatsValue from './item_stats_value.vue';
|
||||
import icon from '~/vue_shared/components/icon.vue';
|
||||
import timeAgoTooltip from '~/vue_shared/components/time_ago_tooltip.vue';
|
||||
import {
|
||||
ITEM_TYPE,
|
||||
VISIBILITY_TYPE_ICON,
|
||||
GROUP_VISIBILITY_TYPE,
|
||||
PROJECT_VISIBILITY_TYPE,
|
||||
} from '../constants';
|
||||
import itemStatsValue from './item_stats_value.vue';
|
||||
|
||||
export default {
|
||||
components: {
|
||||
icon,
|
||||
timeAgoTooltip,
|
||||
itemStatsValue,
|
||||
export default {
|
||||
components: {
|
||||
icon,
|
||||
timeAgoTooltip,
|
||||
itemStatsValue,
|
||||
},
|
||||
props: {
|
||||
item: {
|
||||
type: Object,
|
||||
required: true,
|
||||
},
|
||||
props: {
|
||||
item: {
|
||||
type: Object,
|
||||
required: true,
|
||||
},
|
||||
},
|
||||
computed: {
|
||||
visibilityIcon() {
|
||||
return VISIBILITY_TYPE_ICON[this.item.visibility];
|
||||
},
|
||||
computed: {
|
||||
visibilityIcon() {
|
||||
return VISIBILITY_TYPE_ICON[this.item.visibility];
|
||||
},
|
||||
visibilityTooltip() {
|
||||
if (this.item.type === ITEM_TYPE.GROUP) {
|
||||
return GROUP_VISIBILITY_TYPE[this.item.visibility];
|
||||
}
|
||||
return PROJECT_VISIBILITY_TYPE[this.item.visibility];
|
||||
},
|
||||
isProject() {
|
||||
return this.item.type === ITEM_TYPE.PROJECT;
|
||||
},
|
||||
isGroup() {
|
||||
return this.item.type === ITEM_TYPE.GROUP;
|
||||
},
|
||||
visibilityTooltip() {
|
||||
if (this.item.type === ITEM_TYPE.GROUP) {
|
||||
return GROUP_VISIBILITY_TYPE[this.item.visibility];
|
||||
}
|
||||
return PROJECT_VISIBILITY_TYPE[this.item.visibility];
|
||||
},
|
||||
};
|
||||
isProject() {
|
||||
return this.item.type === ITEM_TYPE.PROJECT;
|
||||
},
|
||||
isGroup() {
|
||||
return this.item.type === ITEM_TYPE.GROUP;
|
||||
},
|
||||
},
|
||||
};
|
||||
</script>
|
||||
|
||||
<template>
|
||||
|
|
|
@ -1,52 +1,52 @@
|
|||
<script>
|
||||
import tooltip from '~/vue_shared/directives/tooltip';
|
||||
import icon from '~/vue_shared/components/icon.vue';
|
||||
import tooltip from '~/vue_shared/directives/tooltip';
|
||||
import icon from '~/vue_shared/components/icon.vue';
|
||||
|
||||
export default {
|
||||
components: {
|
||||
icon,
|
||||
export default {
|
||||
components: {
|
||||
icon,
|
||||
},
|
||||
directives: {
|
||||
tooltip,
|
||||
},
|
||||
props: {
|
||||
title: {
|
||||
type: String,
|
||||
required: false,
|
||||
default: '',
|
||||
},
|
||||
directives: {
|
||||
tooltip,
|
||||
cssClass: {
|
||||
type: String,
|
||||
required: false,
|
||||
default: '',
|
||||
},
|
||||
props: {
|
||||
title: {
|
||||
type: String,
|
||||
required: false,
|
||||
default: '',
|
||||
},
|
||||
cssClass: {
|
||||
type: String,
|
||||
required: false,
|
||||
default: '',
|
||||
},
|
||||
iconName: {
|
||||
type: String,
|
||||
required: true,
|
||||
},
|
||||
tooltipPlacement: {
|
||||
type: String,
|
||||
required: false,
|
||||
default: 'bottom',
|
||||
},
|
||||
/**
|
||||
* value could either be number or string
|
||||
* as `memberCount` is always passed as string
|
||||
* while `subgroupCount` & `projectCount`
|
||||
* are always number
|
||||
*/
|
||||
value: {
|
||||
type: [Number, String],
|
||||
required: false,
|
||||
default: '',
|
||||
},
|
||||
iconName: {
|
||||
type: String,
|
||||
required: true,
|
||||
},
|
||||
computed: {
|
||||
isValuePresent() {
|
||||
return this.value !== '';
|
||||
},
|
||||
tooltipPlacement: {
|
||||
type: String,
|
||||
required: false,
|
||||
default: 'bottom',
|
||||
},
|
||||
};
|
||||
/**
|
||||
* value could either be number or string
|
||||
* as `memberCount` is always passed as string
|
||||
* while `subgroupCount` & `projectCount`
|
||||
* are always number
|
||||
*/
|
||||
value: {
|
||||
type: [Number, String],
|
||||
required: false,
|
||||
default: '',
|
||||
},
|
||||
},
|
||||
computed: {
|
||||
isValuePresent() {
|
||||
return this.value !== '';
|
||||
},
|
||||
},
|
||||
};
|
||||
</script>
|
||||
|
||||
<template>
|
||||
|
|
|
@ -37,20 +37,22 @@ export default class NewGroupChild {
|
|||
|
||||
getDroplabConfig() {
|
||||
return {
|
||||
InputSetter: [{
|
||||
input: this.newGroupChildButton,
|
||||
valueAttribute: 'data-value',
|
||||
inputAttribute: 'data-action',
|
||||
}, {
|
||||
input: this.newGroupChildButton,
|
||||
valueAttribute: 'data-text',
|
||||
}],
|
||||
InputSetter: [
|
||||
{
|
||||
input: this.newGroupChildButton,
|
||||
valueAttribute: 'data-value',
|
||||
inputAttribute: 'data-action',
|
||||
},
|
||||
{
|
||||
input: this.newGroupChildButton,
|
||||
valueAttribute: 'data-text',
|
||||
},
|
||||
],
|
||||
};
|
||||
}
|
||||
|
||||
bindEvents() {
|
||||
this.newGroupChildButton
|
||||
.addEventListener('click', this.onClickNewGroupChildButton.bind(this));
|
||||
this.newGroupChildButton.addEventListener('click', this.onClickNewGroupChildButton.bind(this));
|
||||
}
|
||||
|
||||
onClickNewGroupChildButton(e) {
|
||||
|
|
|
@ -17,13 +17,14 @@ export default class GroupsStore {
|
|||
}
|
||||
|
||||
setSearchedGroups(rawGroups) {
|
||||
const formatGroups = groups => groups.map((group) => {
|
||||
const formattedGroup = this.formatGroupItem(group);
|
||||
if (formattedGroup.children && formattedGroup.children.length) {
|
||||
formattedGroup.children = formatGroups(formattedGroup.children);
|
||||
}
|
||||
return formattedGroup;
|
||||
});
|
||||
const formatGroups = groups =>
|
||||
groups.map(group => {
|
||||
const formattedGroup = this.formatGroupItem(group);
|
||||
if (formattedGroup.children && formattedGroup.children.length) {
|
||||
formattedGroup.children = formatGroups(formattedGroup.children);
|
||||
}
|
||||
return formattedGroup;
|
||||
});
|
||||
|
||||
if (rawGroups && rawGroups.length) {
|
||||
this.state.groups = formatGroups(rawGroups);
|
||||
|
@ -62,10 +63,10 @@ export default class GroupsStore {
|
|||
|
||||
formatGroupItem(rawGroupItem) {
|
||||
const groupChildren = rawGroupItem.children || [];
|
||||
const groupIsOpen = (groupChildren.length > 0) || false;
|
||||
const childrenCount = this.hideProjects ?
|
||||
rawGroupItem.subgroup_count :
|
||||
rawGroupItem.children_count;
|
||||
const groupIsOpen = groupChildren.length > 0 || false;
|
||||
const childrenCount = this.hideProjects
|
||||
? rawGroupItem.subgroup_count
|
||||
: rawGroupItem.children_count;
|
||||
|
||||
return {
|
||||
id: rawGroupItem.id,
|
||||
|
|
|
@ -22,7 +22,7 @@ export default class TransferDropdown {
|
|||
search: { fields: ['text'] },
|
||||
data: extraOptions.concat(this.data),
|
||||
text: item => item.text,
|
||||
clicked: (options) => {
|
||||
clicked: options => {
|
||||
const { e } = options;
|
||||
e.preventDefault();
|
||||
this.assignSelected(options.selectedObj);
|
||||
|
|
|
@ -23,7 +23,7 @@ export default function groupsSelect() {
|
|||
axios[params.type.toLowerCase()](params.url, {
|
||||
params: params.data,
|
||||
})
|
||||
.then((res) => {
|
||||
.then(res => {
|
||||
const results = res.data || [];
|
||||
const headers = normalizeHeaders(res.headers);
|
||||
const currentPage = parseInt(headers['X-PAGE'], 10) || 0;
|
||||
|
@ -36,7 +36,8 @@ export default function groupsSelect() {
|
|||
more,
|
||||
},
|
||||
});
|
||||
}).catch(params.error);
|
||||
})
|
||||
.catch(params.error);
|
||||
},
|
||||
data(search, page) {
|
||||
return {
|
||||
|
@ -68,7 +69,9 @@ export default function groupsSelect() {
|
|||
}
|
||||
},
|
||||
formatResult(object) {
|
||||
return `<div class='group-result'> <div class='group-name'>${object.full_name}</div> <div class='group-path'>${object.full_path}</div> </div>`;
|
||||
return `<div class='group-result'> <div class='group-name'>${
|
||||
object.full_name
|
||||
}</div> <div class='group-path'>${object.full_path}</div> </div>`;
|
||||
},
|
||||
formatSelection(object) {
|
||||
return object.full_name;
|
||||
|
|
|
@ -19,7 +19,9 @@ export function renderIdenticon(entity, options = {}) {
|
|||
const bgClass = getIdenticonBackgroundClass(entity.id);
|
||||
const title = getIdenticonTitle(entity.name);
|
||||
|
||||
return `<div class="avatar identicon ${_.escape(sizeClass)} ${_.escape(bgClass)}">${_.escape(title)}</div>`;
|
||||
return `<div class="avatar identicon ${_.escape(sizeClass)} ${_.escape(bgClass)}">${_.escape(
|
||||
title,
|
||||
)}</div>`;
|
||||
}
|
||||
|
||||
export function renderAvatar(entity, options = {}) {
|
||||
|
|
|
@ -60,8 +60,10 @@ export default class ImageDiff {
|
|||
}
|
||||
|
||||
renderBadge(discussionEl, index) {
|
||||
const imageBadge = imageDiffHelper
|
||||
.generateBadgeFromDiscussionDOM(this.imageFrameEl, discussionEl);
|
||||
const imageBadge = imageDiffHelper.generateBadgeFromDiscussionDOM(
|
||||
this.imageFrameEl,
|
||||
discussionEl,
|
||||
);
|
||||
|
||||
this.imageBadges.push(imageBadge);
|
||||
|
||||
|
|
|
@ -8,5 +8,6 @@ export default () => {
|
|||
|
||||
const diffFileEls = document.querySelectorAll('.timeline-content .diff-file.js-image-file');
|
||||
[...diffFileEls].forEach(diffFileEl =>
|
||||
imageDiffHelper.initImageDiff(diffFileEl, canCreateNote, renderCommentBadge));
|
||||
imageDiffHelper.initImageDiff(diffFileEl, canCreateNote, renderCommentBadge),
|
||||
);
|
||||
};
|
||||
|
|
|
@ -26,7 +26,7 @@ export default class ReplacedImageDiff extends ImageDiff {
|
|||
this.imageEls = {};
|
||||
|
||||
const viewTypeNames = Object.getOwnPropertyNames(viewTypes);
|
||||
viewTypeNames.forEach((viewType) => {
|
||||
viewTypeNames.forEach(viewType => {
|
||||
this.imageEls[viewType] = this.imageFrameEls[viewType].querySelector('img');
|
||||
});
|
||||
}
|
||||
|
@ -79,13 +79,12 @@ export default class ReplacedImageDiff extends ImageDiff {
|
|||
|
||||
// Re-render indicator in new view
|
||||
if (indicator.removed) {
|
||||
const normalizedIndicator = imageDiffHelper
|
||||
.resizeCoordinatesToImageElement(this.imageEl, {
|
||||
x: indicator.x,
|
||||
y: indicator.y,
|
||||
width: indicator.image.width,
|
||||
height: indicator.image.height,
|
||||
});
|
||||
const normalizedIndicator = imageDiffHelper.resizeCoordinatesToImageElement(this.imageEl, {
|
||||
x: indicator.x,
|
||||
y: indicator.y,
|
||||
width: indicator.image.width,
|
||||
height: indicator.image.height,
|
||||
});
|
||||
imageDiffHelper.showCommentIndicator(this.imageFrameEl, normalizedIndicator);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -60,66 +60,71 @@ class ImporterStatus {
|
|||
attributes = Object.assign(repoData, attributes);
|
||||
}
|
||||
|
||||
return axios.post(this.importUrl, attributes)
|
||||
.then(({ data }) => {
|
||||
const job = $(`tr#repo_${id}`);
|
||||
job.attr('id', `project_${data.id}`);
|
||||
return axios
|
||||
.post(this.importUrl, attributes)
|
||||
.then(({ data }) => {
|
||||
const job = $(`tr#repo_${id}`);
|
||||
job.attr('id', `project_${data.id}`);
|
||||
|
||||
job.find('.import-target').html(`<a href="${data.full_path}">${data.full_path}</a>`);
|
||||
$('table.import-jobs tbody').prepend(job);
|
||||
job.find('.import-target').html(`<a href="${data.full_path}">${data.full_path}</a>`);
|
||||
$('table.import-jobs tbody').prepend(job);
|
||||
|
||||
job.addClass('table-active');
|
||||
const connectingVerb = this.ciCdOnly ? __('connecting') : __('importing');
|
||||
job.find('.import-actions').html(sprintf(
|
||||
_.escape(__('%{loadingIcon} Started')), {
|
||||
loadingIcon: `<i class="fa fa-spinner fa-spin" aria-label="${_.escape(connectingVerb)}"></i>`,
|
||||
},
|
||||
false,
|
||||
));
|
||||
})
|
||||
.catch((error) => {
|
||||
let details = error;
|
||||
job.addClass('table-active');
|
||||
const connectingVerb = this.ciCdOnly ? __('connecting') : __('importing');
|
||||
job.find('.import-actions').html(
|
||||
sprintf(
|
||||
_.escape(__('%{loadingIcon} Started')),
|
||||
{
|
||||
loadingIcon: `<i class="fa fa-spinner fa-spin" aria-label="${_.escape(
|
||||
connectingVerb,
|
||||
)}"></i>`,
|
||||
},
|
||||
false,
|
||||
),
|
||||
);
|
||||
})
|
||||
.catch(error => {
|
||||
let details = error;
|
||||
|
||||
const $statusField = $(`#repo_${this.id} .job-status`);
|
||||
$statusField.text(__('Failed'));
|
||||
const $statusField = $(`#repo_${this.id} .job-status`);
|
||||
$statusField.text(__('Failed'));
|
||||
|
||||
if (error.response && error.response.data && error.response.data.errors) {
|
||||
details = error.response.data.errors;
|
||||
}
|
||||
if (error.response && error.response.data && error.response.data.errors) {
|
||||
details = error.response.data.errors;
|
||||
}
|
||||
|
||||
flash(sprintf(__('An error occurred while importing project: %{details}'), { details }));
|
||||
});
|
||||
flash(sprintf(__('An error occurred while importing project: %{details}'), { details }));
|
||||
});
|
||||
}
|
||||
|
||||
autoUpdate() {
|
||||
return axios.get(this.jobsUrl)
|
||||
.then(({ data = [] }) => {
|
||||
data.forEach((job) => {
|
||||
const jobItem = $(`#project_${job.id}`);
|
||||
const statusField = jobItem.find('.job-status');
|
||||
return axios.get(this.jobsUrl).then(({ data = [] }) => {
|
||||
data.forEach(job => {
|
||||
const jobItem = $(`#project_${job.id}`);
|
||||
const statusField = jobItem.find('.job-status');
|
||||
|
||||
const spinner = '<i class="fa fa-spinner fa-spin"></i>';
|
||||
const spinner = '<i class="fa fa-spinner fa-spin"></i>';
|
||||
|
||||
switch (job.import_status) {
|
||||
case 'finished':
|
||||
jobItem.removeClass('table-active').addClass('table-success');
|
||||
statusField.html(`<span><i class="fa fa-check"></i> ${__('Done')}</span>`);
|
||||
break;
|
||||
case 'scheduled':
|
||||
statusField.html(`${spinner} ${__('Scheduled')}`);
|
||||
break;
|
||||
case 'started':
|
||||
statusField.html(`${spinner} ${__('Started')}`);
|
||||
break;
|
||||
case 'failed':
|
||||
statusField.html(__('Failed'));
|
||||
break;
|
||||
default:
|
||||
statusField.html(job.import_status);
|
||||
break;
|
||||
}
|
||||
});
|
||||
switch (job.import_status) {
|
||||
case 'finished':
|
||||
jobItem.removeClass('table-active').addClass('table-success');
|
||||
statusField.html(`<span><i class="fa fa-check"></i> ${__('Done')}</span>`);
|
||||
break;
|
||||
case 'scheduled':
|
||||
statusField.html(`${spinner} ${__('Scheduled')}`);
|
||||
break;
|
||||
case 'started':
|
||||
statusField.html(`${spinner} ${__('Started')}`);
|
||||
break;
|
||||
case 'failed':
|
||||
statusField.html(__('Failed'));
|
||||
break;
|
||||
default:
|
||||
statusField.html(job.import_status);
|
||||
break;
|
||||
}
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
setAutoUpdate() {
|
||||
|
@ -141,7 +146,4 @@ function initImporterStatus() {
|
|||
}
|
||||
}
|
||||
|
||||
export {
|
||||
initImporterStatus as default,
|
||||
ImporterStatus,
|
||||
};
|
||||
export { initImporterStatus as default, ImporterStatus };
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
import $ from 'jquery';
|
||||
import { stickyMonitor } from './lib/utils/sticky';
|
||||
|
||||
export default (stickyTop) => {
|
||||
export default stickyTop => {
|
||||
stickyMonitor(document.querySelector('.js-diff-files-changed'), stickyTop);
|
||||
|
||||
$('.js-diff-stats-dropdown').glDropdown({
|
||||
|
|
|
@ -2,13 +2,7 @@ import Notes from './notes';
|
|||
|
||||
export default () => {
|
||||
const dataEl = document.querySelector('.js-notes-data');
|
||||
const {
|
||||
notesUrl,
|
||||
notesIds,
|
||||
now,
|
||||
diffView,
|
||||
enableGFM,
|
||||
} = JSON.parse(dataEl.innerHTML);
|
||||
const { notesUrl, notesIds, now, diffView, enableGFM } = JSON.parse(dataEl.innerHTML);
|
||||
|
||||
// Create a singleton so that we don't need to assign
|
||||
// into the window object, we can just access the current isntance with Notes.instance
|
||||
|
|
|
@ -97,7 +97,8 @@ export default class IntegrationSettingsForm {
|
|||
testSettings(formData) {
|
||||
this.toggleSubmitBtnState(true);
|
||||
|
||||
return axios.put(this.testEndPoint, formData)
|
||||
return axios
|
||||
.put(this.testEndPoint, formData)
|
||||
.then(({ data }) => {
|
||||
if (data.error) {
|
||||
let flashActions;
|
||||
|
@ -105,7 +106,7 @@ export default class IntegrationSettingsForm {
|
|||
if (data.test_failed) {
|
||||
flashActions = {
|
||||
title: 'Save anyway',
|
||||
clickHandler: (e) => {
|
||||
clickHandler: e => {
|
||||
e.preventDefault();
|
||||
this.$form.submit();
|
||||
},
|
||||
|
|
|
@ -27,7 +27,10 @@ class AutoWidthDropdownSelect {
|
|||
|
||||
// We have to look at the parent because
|
||||
// `offsetParent` on a `display: none;` is `null`
|
||||
const offsetParentWidth = $(this).parent().offsetParent().width();
|
||||
const offsetParentWidth = $(this)
|
||||
.parent()
|
||||
.offsetParent()
|
||||
.width();
|
||||
// Reset any width to let it naturally flow
|
||||
$dropdown.css('width', 'auto');
|
||||
if ($dropdown.outerWidth(false) > offsetParentWidth) {
|
||||
|
|
|
@ -32,7 +32,7 @@ export default {
|
|||
|
||||
onFormSubmitFailure() {
|
||||
this.form.find('[type="submit"]').enable();
|
||||
return new Flash("Issue update failed");
|
||||
return new Flash('Issue update failed');
|
||||
},
|
||||
|
||||
getSelectedIssues() {
|
||||
|
@ -63,7 +63,7 @@ export default {
|
|||
const result = [];
|
||||
const labelsToKeep = this.$labelDropdown.data('indeterminate');
|
||||
|
||||
this.getLabelsFromSelection().forEach((id) => {
|
||||
this.getLabelsFromSelection().forEach(id => {
|
||||
if (labelsToKeep.indexOf(id) === -1) {
|
||||
result.push(id);
|
||||
}
|
||||
|
@ -89,8 +89,8 @@ export default {
|
|||
issuable_ids: this.form.find('input[name="update[issuable_ids]"]').val(),
|
||||
subscription_event: this.form.find('input[name="update[subscription_event]"]').val(),
|
||||
add_label_ids: [],
|
||||
remove_label_ids: []
|
||||
}
|
||||
remove_label_ids: [],
|
||||
},
|
||||
};
|
||||
if (this.willUpdateLabels) {
|
||||
formData.update.add_label_ids = this.$labelDropdown.data('marked');
|
||||
|
@ -134,7 +134,7 @@ export default {
|
|||
// Collect unique label IDs for all checked issues
|
||||
this.getElement('.selected-issuable:checked').each((i, el) => {
|
||||
issuableLabels = this.getElement(`#${this.prefixId}${el.dataset.id}`).data('labels');
|
||||
issuableLabels.forEach((labelId) => {
|
||||
issuableLabels.forEach(labelId => {
|
||||
// Store unique IDs
|
||||
if (uniqueIds.indexOf(labelId) === -1) {
|
||||
uniqueIds.push(labelId);
|
||||
|
|
Loading…
Reference in a new issue