Commit d2ee2eab authored by Mike Greiling's avatar Mike Greiling

Prettify app/assets/javascripts/pages

parent d87e88a6
......@@ -31,7 +31,7 @@ export default class AbuseReports {
$messageCellElement.text(originalMessage);
} else {
$messageCellElement.data('messageTruncated', 'true');
$messageCellElement.text(`${originalMessage.substr(0, (MAX_MESSAGE_LENGTH - 3))}...`);
$messageCellElement.text(`${originalMessage.substr(0, MAX_MESSAGE_LENGTH - 3)}...`);
}
}
}
......@@ -23,7 +23,7 @@ export default function adminInit() {
}
});
$('body').on('click', '.js-toggle-colors-link', (e) => {
$('body').on('click', '.js-toggle-colors-link', e => {
e.preventDefault();
$('.js-toggle-colors-container').toggleClass('hide');
});
......@@ -33,12 +33,15 @@ export default function adminInit() {
$(this).tab('show');
});
$('.log-bottom').on('click', (e) => {
$('.log-bottom').on('click', e => {
e.preventDefault();
const $visibleLog = $('.file-content:visible');
$visibleLog.animate({
scrollTop: $visibleLog.find('ol').height(),
}, 'fast');
$visibleLog.animate(
{
scrollTop: $visibleLog.find('ol').height(),
},
'fast',
);
});
$('.change-owner-link').on('click', function changeOwnerLinkClick(e) {
......@@ -47,7 +50,7 @@ export default function adminInit() {
modal.show();
});
$('.change-owner-cancel-link').on('click', (e) => {
$('.change-owner-cancel-link').on('click', e => {
e.preventDefault();
modal.hide();
$('.change-owner-link').show();
......
import { __ } from '~/locale';
export const PLACEHOLDER_USER_EXTERNAL_DEFAULT_TRUE = __('Regex pattern');
export const PLACEHOLDER_USER_EXTERNAL_DEFAULT_FALSE = __('To define internal users, first enable new users set to external');
export const PLACEHOLDER_USER_EXTERNAL_DEFAULT_FALSE = __(
'To define internal users, first enable new users set to external',
);
function setUserInternalRegexPlaceholder(checkbox) {
const userInternalRegex = document.getElementById('application_setting_user_default_internal_regex');
const userInternalRegex = document.getElementById(
'application_setting_user_default_internal_regex',
);
if (checkbox && userInternalRegex) {
if (checkbox.checked) {
userInternalRegex.readOnly = false;
......
......@@ -17,20 +17,24 @@ export default () => {
const previewPath = $('textarea#broadcast_message_message').data('previewPath');
$('textarea#broadcast_message_message').on('input', _.debounce(function onMessageInput() {
const message = $(this).val();
if (message === '') {
$('.js-broadcast-message-preview').text('Your message here');
} else {
axios.post(previewPath, {
broadcast_message: {
message,
},
})
.then(({ data }) => {
$('.js-broadcast-message-preview').html(data.message);
})
.catch(() => flash(__('An error occurred while rendering preview broadcast message')));
}
}, 250));
$('textarea#broadcast_message_message').on(
'input',
_.debounce(function onMessageInput() {
const message = $(this).val();
if (message === '') {
$('.js-broadcast-message-preview').text('Your message here');
} else {
axios
.post(previewPath, {
broadcast_message: {
message,
},
})
.then(({ data }) => {
$('.js-broadcast-message-preview').html(data.message);
})
.catch(() => flash(__('An error occurred while rendering preview broadcast message')));
}
}, 250),
);
};
<script>
import axios from '~/lib/utils/axios_utils';
import createFlash from '~/flash';
import GlModal from '~/vue_shared/components/gl_modal.vue';
import { redirectTo } from '~/lib/utils/url_utility';
import { s__ } from '~/locale';
import axios from '~/lib/utils/axios_utils';
import createFlash from '~/flash';
import GlModal from '~/vue_shared/components/gl_modal.vue';
import { redirectTo } from '~/lib/utils/url_utility';
import { s__ } from '~/locale';
export default {
components: {
GlModal,
export default {
components: {
GlModal,
},
props: {
url: {
type: String,
required: true,
},
props: {
url: {
type: String,
required: true,
},
},
computed: {
text() {
return s__(
'AdminArea|You’re about to stop all jobs.This will halt all current jobs that are running.',
);
},
computed: {
text() {
return s__('AdminArea|You’re about to stop all jobs.This will halt all current jobs that are running.');
},
},
methods: {
onSubmit() {
return axios
.post(this.url)
.then(response => {
// follow the rediect to refresh the page
redirectTo(response.request.responseURL);
})
.catch(error => {
createFlash(s__('AdminArea|Stopping jobs failed'));
throw error;
});
},
methods: {
onSubmit() {
return axios.post(this.url)
.then((response) => {
// follow the rediect to refresh the page
redirectTo(response.request.responseURL);
})
.catch((error) => {
createFlash(s__('AdminArea|Stopping jobs failed'));
throw error;
});
},
},
};
},
};
</script>
<template>
......
......@@ -4,6 +4,7 @@ import NamespaceSelect from '../../../namespace_select';
document.addEventListener('DOMContentLoaded', () => {
new ProjectsList(); // eslint-disable-line no-new
document.querySelectorAll('.js-namespace-select')
document
.querySelectorAll('.js-namespace-select')
.forEach(dropdown => new NamespaceSelect({ dropdown }));
});
<script>
import _ from 'underscore';
import DeprecatedModal from '~/vue_shared/components/deprecated_modal.vue';
import { s__, sprintf } from '~/locale';
import _ from 'underscore';
import DeprecatedModal from '~/vue_shared/components/deprecated_modal.vue';
import { s__, sprintf } from '~/locale';
export default {
components: {
DeprecatedModal,
export default {
components: {
DeprecatedModal,
},
props: {
deleteProjectUrl: {
type: String,
required: false,
default: '',
},
props: {
deleteProjectUrl: {
type: String,
required: false,
default: '',
},
projectName: {
type: String,
required: false,
default: '',
},
csrfToken: {
type: String,
required: false,
default: '',
},
projectName: {
type: String,
required: false,
default: '',
},
data() {
return {
enteredProjectName: '',
};
csrfToken: {
type: String,
required: false,
default: '',
},
computed: {
title() {
return sprintf(s__('AdminProjects|Delete Project %{projectName}?'),
{
projectName: `'${_.escape(this.projectName)}'`,
},
false,
);
},
text() {
return sprintf(s__(`AdminProjects|
},
data() {
return {
enteredProjectName: '',
};
},
computed: {
title() {
return sprintf(
s__('AdminProjects|Delete Project %{projectName}?'),
{
projectName: `'${_.escape(this.projectName)}'`,
},
false,
);
},
text() {
return sprintf(
s__(`AdminProjects|
You’re about to permanently delete the project %{projectName}, its repository,
and all related resources including issues, merge requests, etc.. Once you confirm and press
%{strong_start}Delete project%{strong_end}, it cannot be undone or recovered.`),
{
projectName: `<strong>${_.escape(this.projectName)}</strong>`,
strong_start: '<strong>',
strong_end: '</strong>',
},
false,
);
},
confirmationTextLabel() {
return sprintf(s__('AdminUsers|To confirm, type %{projectName}'),
{
projectName: `<code>${_.escape(this.projectName)}</code>`,
},
false,
);
},
primaryButtonLabel() {
return s__('AdminProjects|Delete project');
},
canSubmit() {
return this.enteredProjectName === this.projectName;
},
{
projectName: `<strong>${_.escape(this.projectName)}</strong>`,
strong_start: '<strong>',
strong_end: '</strong>',
},
false,
);
},
confirmationTextLabel() {
return sprintf(
s__('AdminUsers|To confirm, type %{projectName}'),
{
projectName: `<code>${_.escape(this.projectName)}</code>`,
},
false,
);
},
primaryButtonLabel() {
return s__('AdminProjects|Delete project');
},
canSubmit() {
return this.enteredProjectName === this.projectName;
},
},
methods: {
onCancel() {
this.enteredProjectName = '';
},
methods: {
onCancel() {
this.enteredProjectName = '';
},
onSubmit() {
this.$refs.form.submit();
this.enteredProjectName = '';
},
onSubmit() {
this.$refs.form.submit();
this.enteredProjectName = '';
},
};
},
};
</script>
<template>
......
......@@ -28,7 +28,7 @@ document.addEventListener('DOMContentLoaded', () => {
},
});
$(document).on('shown.bs.modal', (event) => {
$(document).on('shown.bs.modal', event => {
if (event.relatedTarget.classList.contains('delete-project-button')) {
const buttonProps = event.relatedTarget.dataset;
deleteModal.deleteProjectUrl = buttonProps.deleteProjectUrl;
......
<script>
import _ from 'underscore';
import DeprecatedModal from '~/vue_shared/components/deprecated_modal.vue';
import { s__, sprintf } from '~/locale';
import _ from 'underscore';
import DeprecatedModal from '~/vue_shared/components/deprecated_modal.vue';
import { s__, sprintf } from '~/locale';
export default {
components: {
DeprecatedModal,
export default {
components: {
DeprecatedModal,
},
props: {
deleteUserUrl: {
type: String,
required: false,
default: '',
},
props: {
deleteUserUrl: {
type: String,
required: false,
default: '',
},
blockUserUrl: {
type: String,
required: false,
default: '',
},
deleteContributions: {
type: Boolean,
required: false,
default: false,
},
username: {
type: String,
required: false,
default: '',
},
csrfToken: {
type: String,
required: false,
default: '',
},
blockUserUrl: {
type: String,
required: false,
default: '',
},
data() {
return {
enteredUsername: '',
};
deleteContributions: {
type: Boolean,
required: false,
default: false,
},
computed: {
title() {
const keepContributionsTitle = s__('AdminUsers|Delete User %{username}?');
const deleteContributionsTitle = s__('AdminUsers|Delete User %{username} and contributions?');
username: {
type: String,
required: false,
default: '',
},
csrfToken: {
type: String,
required: false,
default: '',
},
},
data() {
return {
enteredUsername: '',
};
},
computed: {
title() {
const keepContributionsTitle = s__('AdminUsers|Delete User %{username}?');
const deleteContributionsTitle = s__('AdminUsers|Delete User %{username} and contributions?');
return sprintf(
this.deleteContributions ? deleteContributionsTitle : keepContributionsTitle, {
username: `'${_.escape(this.username)}'`,
}, false);
},
text() {
const keepContributionsText = s__(`AdminArea|
return sprintf(
this.deleteContributions ? deleteContributionsTitle : keepContributionsTitle,
{
username: `'${_.escape(this.username)}'`,
},
false,
);
},
text() {
const keepContributionsText = s__(`AdminArea|
You are about to permanently delete the user %{username}.
Issues, merge requests, and groups linked to them will be transferred to a system-wide "Ghost-user".
To avoid data loss, consider using the %{strong_start}block user%{strong_end} feature instead.
Once you %{strong_start}Delete user%{strong_end}, it cannot be undone or recovered.`);
const deleteContributionsText = s__(`AdminArea|
const deleteContributionsText = s__(`AdminArea|
You are about to permanently delete the user %{username}.
This will delete all of the issues, merge requests, and groups linked to them.
To avoid data loss, consider using the %{strong_start}block user%{strong_end} feature instead.
Once you %{strong_start}Delete user%{strong_end}, it cannot be undone or recovered.`);
return sprintf(this.deleteContributions ? deleteContributionsText : keepContributionsText,
{
username: `<strong>${_.escape(this.username)}</strong>`,
strong_start: '<strong>',
strong_end: '</strong>',
},
false,
);
},
confirmationTextLabel() {
return sprintf(s__('AdminUsers|To confirm, type %{username}'),
{
username: `<code>${_.escape(this.username)}</code>`,
},
false,
);
},
primaryButtonLabel() {
const keepContributionsLabel = s__('AdminUsers|Delete user');
const deleteContributionsLabel = s__('AdminUsers|Delete user and contributions');
return sprintf(
this.deleteContributions ? deleteContributionsText : keepContributionsText,
{
username: `<strong>${_.escape(this.username)}</strong>`,
strong_start: '<strong>',
strong_end: '</strong>',
},
false,
);
},
confirmationTextLabel() {
return sprintf(
s__('AdminUsers|To confirm, type %{username}'),
{
username: `<code>${_.escape(this.username)}</code>`,
},
false,
);
},
primaryButtonLabel() {
const keepContributionsLabel = s__('AdminUsers|Delete user');
const deleteContributionsLabel = s__('AdminUsers|Delete user and contributions');
return this.deleteContributions ? deleteContributionsLabel : keepContributionsLabel;
},
secondaryButtonLabel() {
return s__('AdminUsers|Block user');
},
canSubmit() {
return this.enteredUsername === this.username;
},
return this.deleteContributions ? deleteContributionsLabel : keepContributionsLabel;
},
methods: {
onCancel() {
this.enteredUsername = '';
},
onSecondaryAction() {
const { form } = this.$refs;
secondaryButtonLabel() {
return s__('AdminUsers|Block user');
},
canSubmit() {
return this.enteredUsername === this.username;
},
},
methods: {
onCancel() {
this.enteredUsername = '';
},
onSecondaryAction() {
const { form } = this.$refs;
form.action = this.blockUserUrl;
this.$refs.method.value = 'put';
form.action = this.blockUserUrl;
this.$refs.method.value = 'put';
form.submit();
},
onSubmit() {
this.$refs.form.submit();
this.enteredUsername = '';
},
form.submit();
},
onSubmit() {
this.$refs.form.submit();
this.enteredUsername = '';
},
};
},
};
</script>
<template>
......
......@@ -32,12 +32,14 @@ document.addEventListener('DOMContentLoaded', () => {
},
});
$(document).on('shown.bs.modal', (event) => {
$(document).on('shown.bs.modal', event => {
if (event.relatedTarget.classList.contains('delete-user-button')) {
const buttonProps = event.relatedTarget.dataset;
deleteModal.deleteUserUrl = buttonProps.deleteUserUrl;
deleteModal.blockUserUrl = buttonProps.blockUserUrl;
deleteModal.deleteContributions = event.relatedTarget.hasAttribute('data-delete-contributions');
deleteModal.deleteContributions = event.relatedTarget.hasAttribute(
'data-delete-contributions',
);
deleteModal.username = buttonProps.username;
}
});
......
......@@ -4,7 +4,9 @@ export default class UserInternalRegexHandler {
constructor() {
this.regexPattern = $('[data-user-internal-regex-pattern]').data('user-internal-regex-pattern');
if (this.regexPattern && this.regexPattern !== '') {
this.regexOptions = $('[data-user-internal-regex-options]').data('user-internal-regex-options');
this.regexOptions = $('[data-user-internal-regex-options]').data(
'user-internal-regex-options',
);
this.external = $('#user_external');
this.warningMessage = $('#warning_external_automatically_set');
this.addListenerToEmailField();
......@@ -13,7 +15,7 @@ export default class UserInternalRegexHandler {
}
addListenerToEmailField() {
$('#user_email').on('input', (event) => {
$('#user_email').on('input', event => {
this.setExternalCheckbox(event.currentTarget.value);
});
}
......
......@@ -79,7 +79,8 @@ export default class Todos {
.then(({ data }) => {
this.updateRowState(target);
this.updateBadges(data);
}).catch(() => {
})
.catch(() => {
this.updateRowState(target, true);
return flash(__('Error updating todo status.'));
});
......@@ -118,10 +119,12 @@ export default class Todos {
axios[target.dataset.method](target.dataset.href, {
ids: this.todo_ids,
}).then(({ data }) => {
this.updateAllState(target, data);
this.updateBadges(data);
}).catch(() => flash(__('Error updating status for all todos.')));
})
.then(({ data }) => {
this.updateAllState(target, data);
this.updateBadges(data);
})
.catch(() => flash(__('Error updating status for all todos.')));
}
updateAllState(target, data) {
......@@ -133,7 +136,7 @@ export default class Todos {
target.removeAttribute('disabled');
target.classList.remove('disabled');
this.todo_ids = (target === markAllDoneBtn) ? data.updated_ids : [];
this.todo_ids = target === markAllDoneBtn ? data.updated_ids : [];
undoAllBtn.classList.toggle('hidden');
markAllDoneBtn.classList.toggle('hidden');
todoListContainer.classList.toggle('hidden');
......
<script>
import axios from '~/lib/utils/axios_utils';
import axios from '~/lib/utils/axios_utils';
import Flash from '~/flash';
import DeprecatedModal from '~/vue_shared/components/deprecated_modal.vue';
import { n__, s__, sprintf } from '~/locale';
import { redirectTo } from '~/lib/utils/url_utility';
import eventHub from '../event_hub';
import Flash from '~/flash';
import DeprecatedModal from '~/vue_shared/components/deprecated_modal.vue';
import { n__, s__, sprintf } from '~/locale';
import { redirectTo } from '~/lib/utils/url_utility';
import eventHub from '../event_hub';
export default {
components: {
DeprecatedModal,
export default {
components: {
DeprecatedModal,
},
props: {
issueCount: {
type: Number,
required: true,
},
props: {
issueCount: {
type: Number,
required: true,
},
mergeRequestCount: {
type: Number,
required: true,
},
milestoneId: {
type: Number,
required: true,
},
milestoneTitle: {
type: String,
required: true,
},
milestoneUrl: {
type: String,
required: true,
},
mergeRequestCount: {
type: Number,
required: true,
},
computed: {
text() {
const milestoneTitle = sprintf('<strong>%{milestoneTitle}</strong>', { milestoneTitle: this.milestoneTitle });
if (this.issueCount === 0 && this.mergeRequestCount === 0) {
return sprintf(
s__(`Milestones|
You’re about to permanently delete the milestone %{milestoneTitle}.
This milestone is not currently used in any issues or merge requests.`),
{
milestoneTitle,
},
false,
);
}
milestoneId: {
type: Number,
required: true,
},
milestoneTitle: {
type: String,
required: true,
},
milestoneUrl: {
type: String,
required: true,
},
},
computed: {
text() {
const milestoneTitle = sprintf('<strong>%{milestoneTitle}</strong>', {
milestoneTitle: this.milestoneTitle,
});
if (this.issueCount === 0 && this.mergeRequestCount === 0) {
return sprintf(
s__(`Milestones|
You’re about to permanently delete the milestone %{milestoneTitle} and remove it from %{issuesWithCount} and %{mergeRequestsWithCount}.
Once deleted, it cannot be undone or recovered.`),
You’re about to permanently delete the milestone %{milestoneTitle}.
This milestone is not currently used in any issues or merge requests.`),
{
milestoneTitle,
issuesWithCount: n__('%d issue', '%d issues', this.issueCount),
mergeRequestsWithCount: n__('%d merge request', '%d merge requests', this.mergeRequestCount),
},
false,
);
},
title() {
return sprintf(s__('Milestones|Delete milestone %{milestoneTitle}?'), { milestoneTitle: this.milestoneTitle });
},
},
methods: {
onSubmit() {
eventHub.$emit('deleteMilestoneModal.requestStarted', this.milestoneUrl);
}
return axios.delete(this.milestoneUrl)
.then((response) => {
eventHub.$emit('deleteMilestoneModal.requestFinished', { milestoneUrl: this.milestoneUrl, successful: true });
return sprintf(
s__(`Milestones|
You’re about to permanently delete the milestone %{milestoneTitle} and remove it from %{issuesWithCount} and %{mergeRequestsWithCount}.
Once deleted, it cannot be undone or recovered.`),
{
milestoneTitle,
issuesWithCount: n__('%d issue', '%d issues', this.issueCount),
mergeRequestsWithCount: n__(
'%d merge request',
'%d merge requests',
this.mergeRequestCount,
),
},
false,
);
},
title() {
return sprintf(s__('Milestones|Delete milestone %{milestoneTitle}?'), {
milestoneTitle: this.milestoneTitle,
});
},
},
methods: {
onSubmit() {
eventHub.$emit('deleteMilestoneModal.requestStarted', this.milestoneUrl);
// follow the rediect to milestones overview page
redirectTo(response.request.responseURL);
})
.catch((error) => {
eventHub.$emit('deleteMilestoneModal.requestFinished', { milestoneUrl: this.milestoneUrl, successful: false });
return axios
.delete(this.milestoneUrl)
.then(response => {
eventHub.$emit('deleteMilestoneModal.requestFinished', {
milestoneUrl: this.milestoneUrl,
successful: true,
});
if (error.response && error.response.status === 404) {
Flash(sprintf(s__('Milestones|Milestone %{milestoneTitle} was not found'), { milestoneTitle: this.milestoneTitle }));
} else {
Flash(sprintf(s__('Milestones|Failed to delete milestone %{milestoneTitle}'), { milestoneTitle: this.milestoneTitle }));
}
throw error;
// follow the rediect to milestones overview page
redirectTo(response.request.responseURL);
})
.catch(error => {
eventHub.$emit('deleteMilestoneModal.requestFinished', {
milestoneUrl: this.milestoneUrl,
successful: false,
});
},
if (error.response && error.response.status === 404) {
Flash(
sprintf(s__('Milestones|Milestone %{milestoneTitle} was not found'), {
milestoneTitle: this.milestoneTitle,
}),
);
} else {
Flash(
sprintf(s__('Milestones|Failed to delete milestone %{milestoneTitle}'), {
milestoneTitle: this.milestoneTitle,
}),
);
}
throw error;
});
},
};
},
};
</script>
<template>
......
......@@ -7,7 +7,9 @@ export default () => {
Vue.use(Translate);
const onRequestFinished = ({ milestoneUrl, successful }) => {
const button = document.querySelector(`.js-delete-milestone-button[data-milestone-url="${milestoneUrl}"]`);
const button = document.querySelector(
`.js-delete-milestone-button[data-milestone-url="${milestoneUrl}"]`,
);
if (!successful) {
button.removeAttribute('disabled');
......@@ -16,14 +18,16 @@ export default () => {
button.querySelector('.js-loading-icon').classList.add('hidden');
};
const onRequestStarted = (milestoneUrl) => {
const button = document.querySelector(`.js-delete-milestone-button[data-milestone-url="${milestoneUrl}"]`);
const onRequestStarted = milestoneUrl => {
const button = document.querySelector(
`.js-delete-milestone-button[data-milestone-url="${milestoneUrl}"]`,
);
button.setAttribute('disabled', '');
button.querySelector('.js-loading-icon').classList.remove('hidden');
eventHub.$once('deleteMilestoneModal.requestFinished', onRequestFinished);
};
const onDeleteButtonClick = (event) => {
const onDeleteButtonClick = event => {
const button = event.currentTarget;
const modalProps = {
milestoneId: parseInt(button.dataset.milestoneId, 10),
......@@ -37,12 +41,12 @@ export default () => {
};
const deleteMilestoneButtons = document.querySelectorAll('.js-delete-milestone-button');
deleteMilestoneButtons.forEach((button) => {
deleteMilestoneButtons.forEach(button => {
button.addEventListener('click', onDeleteButtonClick);
});
eventHub.$once('deleteMilestoneModal.mounted', () => {
deleteMilestoneButtons.forEach((button) => {
deleteMilestoneButtons.forEach(button => {
button.removeAttribute('disabled');
});
});
......
......@@ -7,20 +7,24 @@ Vue.use(Translate);
export default () => {
const onRequestFinished = ({ milestoneUrl, successful }) => {
const button = document.querySelector(`.js-promote-project-milestone-button[data-url="${milestoneUrl}"]`);
const button = document.querySelector(
`.js-promote-project-milestone-button[data-url="${milestoneUrl}"]`,
);
if (!successful) {
button.removeAttribute('disabled');
}
};
const onRequestStarted = (milestoneUrl) => {
const button = document.querySelector(`.js-promote-project-milestone-button[data-url="${milestoneUrl}"]`);
const onRequestStarted = milestoneUrl => {
const button = document.querySelector(
`.js-promote-project-milestone-button[data-url="${milestoneUrl}"]`,
);
button.setAttribute('disabled', '');
eventHub.$once('promoteMilestoneModal.requestFinished', onRequestFinished);
};
const onDeleteButtonClick = (event) => {
const onDeleteButtonClick = event => {
const button = event.currentTarget;
const modalProps = {
milestoneTitle: button.dataset.milestoneTitle,
......@@ -32,12 +36,12 @@ export default () => {
};
const promoteMilestoneButtons = document.querySelectorAll('.js-promote-project-milestone-button');
promoteMilestoneButtons.forEach((button) => {
promoteMilestoneButtons.forEach(button => {
button.addEventListener('click', onDeleteButtonClick);
});
eventHub.$once('promoteMilestoneModal.mounted', () => {
promoteMilestoneButtons.forEach((button) => {
promoteMilestoneButtons.forEach(button => {
button.removeAttribute('disabled');
});
});
......
......@@ -3,9 +3,12 @@ import '~/profile/gl_crop';
import Profile from '~/profile/profile';
document.addEventListener('DOMContentLoaded', () => {
$(document).on('input.ssh_key', '#key_key', function () { // eslint-disable-line func-names
// eslint-disable-next-line func-names
$(document).on('input.ssh_key', '#key_key', function() {
const $title = $('#key_title');
const comment = $(this).val().match(/^\S+ \S+ (.+)\n?$/);
const comment = $(this)
.val()
.match(/^\S+ \S+ (.+)\n?$/);
// Extract the SSH Key title from its comment
if (comment && comment.length > 1) {
......
......@@ -5,7 +5,9 @@ document.addEventListener('DOMContentLoaded', () => {
const twoFactorNode = document.querySelector('.js-two-factor-auth');
const skippable = twoFactorNode.dataset.twoFactorSkippable === 'true';
if (skippable) {
const button = `<a class="btn btn-sm btn-warning float-right" data-method="patch" href="${twoFactorNode.dataset.two_factor_skip_url}">Configure it later</a>`;
const button = `<a class="btn btn-sm btn-warning float-right" data-method="patch" href="${
twoFactorNode.dataset.two_factor_skip_url
}">Configure it later</a>`;
const flashAlert = document.querySelector('.flash-alert .container-fluid');
if (flashAlert) flashAlert.insertAdjacentHTML('beforeend', button);
}
......
import $ from 'jquery';
import NewBranchForm from '~/new_branch_form';
document.addEventListener('DOMContentLoaded', () => (
new NewBranchForm($('.js-create-branch-form'), JSON.parse(document.getElementById('availableRefs').innerHTML))
));
document.addEventListener(
'DOMContentLoaded',
() =>
new NewBranchForm(
$('.js-create-branch-form'),
JSON.parse(document.getElementById('availableRefs').innerHTML),
),
);
......@@ -31,14 +31,16 @@ document.addEventListener('DOMContentLoaded', () => {
const chartData = data => ({
labels: Object.keys(data),
datasets: [{
fillColor: 'rgba(220,220,220,0.5)',
strokeColor: 'rgba(220,220,220,1)',
barStrokeWidth: 1,
barValueSpacing: 1,
barDatasetSpacing: 1,
data: _.values(data),
}],
datasets: [
{
fillColor: 'rgba(220,220,220,0.5)',
strokeColor: 'rgba(220,220,220,1)',
barStrokeWidth: 1,
barValueSpacing: 1,
barDatasetSpacing: 1,
data: _.values(data),
},
],
});
const hourData = chartData(projectChartData.hour);
......@@ -51,7 +53,9 @@ document.addEventListener('DOMContentLoaded', () => {
responsiveChart($('#month-chart'), monthData);
const data = projectChartData.languages;
const ctx = $('#languages-chart').get(0).getContext('2d');
const ctx = $('#languages-chart')
.get(0)
.getContext('2d');
const options = {
scaleOverlay: true,
responsive: true,
......
......@@ -7,7 +7,8 @@ import ContributorsStatGraph from './stat_graph_contributors';
document.addEventListener('DOMContentLoaded', () => {
const url = document.querySelector('.js-graphs-show').dataset.projectGraphPath;
axios.get(url)
axios
.get(url)
.then(({ data }) => {
const graph = new ContributorsStatGraph();
graph.init(data);
......
......@@ -3,7 +3,11 @@
import $ from 'jquery';
import _ from 'underscore';
import { n__, s__, createDateTimeFormat, sprintf } from '~/locale';
import { ContributorsGraph, ContributorsAuthorGraph, ContributorsMasterGraph } from './stat_graph_contributors_graph';
import {
ContributorsGraph,
ContributorsAuthorGraph,
ContributorsMasterGraph,
} from './stat_graph_contributors_graph';
import ContributorsStatGraphUtil from './stat_graph_contributors_util';
export default (function() {
......@@ -14,7 +18,7 @@ export default (function() {
ContributorsStatGraph.prototype.init = function(log) {
var author_commits, total_commits;
this.parsed_log = ContributorsStatGraphUtil.parse_log(log);
this.set_current_field("commits");
this.set_current_field('commits');
total_commits = ContributorsStatGraphUtil.get_total_data(this.parsed_log, this.field);
author_commits = ContributorsStatGraphUtil.get_author_data(this.parsed_log, this.field);
this.add_master_graph(total_commits);
......@@ -31,23 +35,26 @@ export default (function() {
var limited_author_data;
this.authors = [];
limited_author_data = author_data.slice(0, 100);
return _.each(limited_author_data, (function(_this) {
return function(d) {
var author_graph, author_header;
author_header = _this.create_author_header(d);
$(".contributors-list").append(author_header);
author_graph = new ContributorsAuthorGraph(d.dates);
_this.authors[d.author_name] = author_graph;
return author_graph.draw();
};
})(this));
return _.each(
limited_author_data,
(function(_this) {
return function(d) {
var author_graph, author_header;
author_header = _this.create_author_header(d);
$('.contributors-list').append(author_header);
author_graph = new ContributorsAuthorGraph(d.dates);
_this.authors[d.author_name] = author_graph;
return author_graph.draw();
};
})(this),
);
};
ContributorsStatGraph.prototype.format_author_commit_info = function(author) {
var commits;
commits = $('<span/>', {
"class": 'graph-author-commits-count'
class: 'graph-author-commits-count',
});
commits.text(n__('%d commit', '%d commits', author.commits));
return $('<span/>').append(commits);
......@@ -56,13 +63,13 @@ export default (function() {
ContributorsStatGraph.prototype.create_author_header = function(author) {
var author_commit_info, author_commit_info_span, author_email, author_name, list_item;
list_item = $('<li/>', {
"class": 'person',
style: 'display: block;'
class: 'person',
style: 'display: block;',
});
author_name = $('<h4>' + author.author_name + '</h4>');
author_email = $('<p class="graph-author-email">' + author.author_email + '</p>');
author_commit_info_span = $('<span/>', {
"class": 'commits'
class: 'commits',
});
author_commit_info = this.format_author_commit_info(author);
author_commit_info_span.html(author_commit_info);
......@@ -80,37 +87,41 @@ export default (function() {
};
ContributorsStatGraph.prototype.redraw_authors = function() {
$("ol").html("");
$('ol').html('');
const { x_domain } = ContributorsGraph.prototype;
const author_commits = ContributorsStatGraphUtil.get_author_data(this.parsed_log, this.field, x_domain);
return _.each(author_commits, (function(_this) {
return function(d) {
_this.redraw_author_commit_info(d);
if (_this.authors[d.author_name] != null) {
$(_this.authors[d.author_name].list_item).appendTo("ol");
_this.authors[d.author_name].set_data(d.dates);
return _this.authors[d.author_name].redraw();
}
return '';
};
})(this));
const author_commits = ContributorsStatGraphUtil.get_author_data(
this.parsed_log,
this.field,
x_domain,
);
return _.each(
author_commits,
(function(_this) {
return function(d) {
_this.redraw_author_commit_info(d);
if (_this.authors[d.author_name] != null) {
$(_this.authors[d.author_name].list_item).appendTo('ol');
_this.authors[d.author_name].set_data(d.dates);
return _this.authors[d.author_name].redraw();
}
return '';
};
})(this),
);
};
ContributorsStatGraph.prototype.set_current_field = function(field) {
return this.field = field;
return (this.field = field);
};
ContributorsStatGraph.prototype.change_date_header = function() {
const { x_domain } = ContributorsGraph.prototype;
const formattedDateRange = sprintf(
s__('ContributorsPage|%{startDate} – %{endDate}'),
{
startDate: this.dateFormat.format(new Date(x_domain[0])),
endDate: this.dateFormat.format(new Date(x_domain[1])),
},
);
const formattedDateRange = sprintf(s__('ContributorsPage|%{startDate} – %{endDate}'), {
startDate: this.dateFormat.format(new Date(x_domain[0])),
endDate: this.dateFormat.format(new Date(x_domain[1])),
});
return $('#date_header').text(formattedDateRange);
};
......@@ -120,7 +131,7 @@ export default (function() {
if ($author != null) {
author_list_item = $(this.authors[author.author_name].list_item);
author_commit_info = this.format_author_commit_info(author);
return author_list_item.find("span").html(author_commit_info);
return author_list_item.find('span').html(author_commit_info);
}
return '';
};
......
......@@ -11,10 +11,32 @@ import { brushX } from 'd3-brush';
import { timeParse } from 'd3-time-format';
import { dateTickFormat } from '~/lib/utils/tick_formats';
const d3 = { extent, max, select, scaleTime, scaleLinear, axisLeft, axisBottom, area, brushX, timeParse };
const d3 = {
extent,
max,
select,
scaleTime,
scaleLinear,
axisLeft,
axisBottom,
area,
brushX,
timeParse,
};
const hasProp = {}.hasOwnProperty;
const extend = function(child, parent) { for (const key in parent) { if (hasProp.call(parent, key)) child[key] = parent[key]; } function ctor() { this.constructor = child; } ctor.prototype = parent.prototype; child.prototype = new ctor(); child.__super__ = parent.prototype; return child; };
const extend = function(child, parent) {
for (const key in parent) {
if (hasProp.call(parent, key)) child[key] = parent[key];
}
function ctor() {
this.constructor = child;
}
ctor.prototype = parent.prototype;
child.prototype = new ctor();
child.__super__ = parent.prototype;
return child;
};
export const ContributorsGraph = (function() {
function ContributorsGraph() {}
......@@ -23,7 +45,7 @@ export const ContributorsGraph = (function() {
top: 20,
right: 10,
bottom: 30,
left: 40
left: 40,
};
ContributorsGraph.prototype.x_domain = null;
......@@ -33,35 +55,39 @@ export const ContributorsGraph = (function() {
ContributorsGraph.prototype.dates = [];
ContributorsGraph.prototype.determine_width = function(baseWidth, $parentElement) {
const parentPaddingWidth = parseFloat($parentElement.css('padding-left')) + parseFloat($parentElement.css('padding-right'));
const parentPaddingWidth =
parseFloat($parentElement.css('padding-left')) +
parseFloat($parentElement.css('padding-right'));
const marginWidth = this.MARGIN.left + this.MARGIN.right;
return baseWidth - parentPaddingWidth - marginWidth;
};
ContributorsGraph.set_x_domain = function(data) {
return ContributorsGraph.prototype.x_domain = data;
return (ContributorsGraph.prototype.x_domain = data);
};
ContributorsGraph.set_y_domain = function(data) {
return ContributorsGraph.prototype.y_domain = [
0, d3.max(data, function(d) {
return d.commits = d.commits || d.additions || d.deletions;
})
];
return (ContributorsGraph.prototype.y_domain = [
0,
d3.max(data, function(d) {
return (d.commits = d.commits || d.additions || d.deletions);
}),
]);
};
ContributorsGraph.init_x_domain = function(data) {
return ContributorsGraph.prototype.x_domain = d3.extent(data, function(d) {
return (ContributorsGraph.prototype.x_domain = d3.extent(data, function(d) {
return d.date;
});
}));
};
ContributorsGraph.init_y_domain = function(data) {
return ContributorsGraph.prototype.y_domain = [
0, d3.max(data, function(d) {
return d.commits = d.commits || d.additions || d.deletions;
})
];
return (ContributorsGraph.prototype.y_domain = [
0,
d3.max(data, function(d) {
return (d.commits = d.commits || d.additions || d.deletions);
}),
]);
};
ContributorsGraph.init_domain = function(data) {
......@@ -70,7 +96,7 @@ export const ContributorsGraph = (function() {
};
ContributorsGraph.set_dates = function(data) {
return ContributorsGraph.prototype.dates = data;
return (ContributorsGraph.prototype.dates = data);
};
ContributorsGraph.prototype.set_x_domain = function() {
......@@ -87,20 +113,33 @@ export const ContributorsGraph = (function() {
};
ContributorsGraph.prototype.create_scale = function(width, height) {
this.x = d3.scaleTime().range([0, width]).clamp(true);
return this.y = d3.scaleLinear().range([height, 0]).nice();
this.x = d3
.scaleTime()
.range([0, width])
.clamp(true);
return (this.y = d3
.scaleLinear()
.range([height, 0])
.nice());
};
ContributorsGraph.prototype.draw_x_axis = function() {
return this.svg.append("g").attr("class", "x axis").attr("transform", "translate(0, " + this.height + ")").call(this.x_axis);
return this.svg
.append('g')
.attr('class', 'x axis')
.attr('transform', 'translate(0, ' + this.height + ')')
.call(this.x_axis);
};
ContributorsGraph.prototype.draw_y_axis = function() {
return this.svg.append("g").attr("class", "y axis").call(this.y_axis);
return this.svg
.append('g')
.attr('class', 'y axis')
.call(this.y_axis);
};
ContributorsGraph.prototype.set_data = function(data) {
return this.data = data;
return (this.data = data);
};
return ContributorsGraph;
......@@ -137,9 +176,9 @@ export const ContributorsMasterGraph = (function(superClass) {
};
ContributorsMasterGraph.prototype.parse_dates = function(data) {
const parseDate = d3.timeParse("%Y-%m-%d");
const parseDate = d3.timeParse('%Y-%m-%d');
return data.forEach(function(d) {
return d.date = parseDate(d.date);
return (d.date = parseDate(d.date));
});
};
......@@ -148,42 +187,63 @@ export const ContributorsMasterGraph = (function(superClass) {
};
ContributorsMasterGraph.prototype.create_axes = function() {
this.x_axis = d3.axisBottom()
this.x_axis = d3
.axisBottom()
.scale(this.x)
.tickFormat(dateTickFormat);
return this.y_axis = d3.axisLeft().scale(this.y).ticks(5);
return (this.y_axis = d3
.axisLeft()
.scale(this.y)
.ticks(5));
};
ContributorsMasterGraph.prototype.create_svg = function() {
this.svg = d3.select("#contributors-master")
.append("svg")
.attr("width", this.width + this.MARGIN.left + this.MARGIN.right)
.attr("height", this.height + this.MARGIN.top + this.MARGIN.bottom)
.attr("class", "tint-box")
.append("g")
.attr("transform", "translate(" + this.MARGIN.left + "," + this.MARGIN.top + ")");
this.svg = d3
.select('#contributors-master')
.append('svg')
.attr('width', this.width + this.MARGIN.left + this.MARGIN.right)
.attr('height', this.height + this.MARGIN.top + this.MARGIN.bottom)
.attr('class', 'tint-box')
.append('g')
.attr('transform', 'translate(' + this.MARGIN.left + ',' + this.MARGIN.top + ')');
return this.svg;
};
ContributorsMasterGraph.prototype.create_area = function(x, y) {
return this.area = d3.area().x(function(d) {
return x(d.date);
}).y0(this.height).y1(function(d) {
d.commits = d.commits || d.additions || d.deletions;
return y(d.commits);
});
return (this.area = d3
.area()
.x(function(d) {
return x(d.date);
})
.y0(this.height)
.y1(function(d) {
d.commits = d.commits || d.additions || d.deletions;
return y(d.commits);
}));
};
ContributorsMasterGraph.prototype.create_brush = function() {
return this.brush = d3.brushX(this.x).extent([[this.x.range()[0], 0], [this.x.range()[1], this.height]]).on("end", this.update_content);
return (this.brush = d3
.brushX(this.x)
.extent([[this.x.range()[0], 0], [this.x.range()[1], this.height]])
.on('end', this.update_content));
};
ContributorsMasterGraph.prototype.draw_path = function(data) {
return this.svg.append("path").datum(data).attr("class", "area").attr("d", this.area);
return this.svg
.append('path')
.datum(data)
.attr('class', 'area')
.attr('d', this.area);
};
ContributorsMasterGraph.prototype.add_brush = function() {
return this.svg.append("g").attr("class", "selection").call(this.brush).selectAll("rect").attr("height", this.height);
return this.svg
.append('g')
.attr('class', 'selection')
.call(this.brush)
.selectAll('rect')
.attr('height', this.height);
};
ContributorsMasterGraph.prototype.update_content = function() {
......@@ -193,7 +253,7 @@ export const ContributorsMasterGraph = (function(superClass) {
} else {
ContributorsGraph.set_x_domain(this.x_max_domain);
}
return $("#brush_change").trigger('change');
return $('#brush_change').trigger('change');
};
ContributorsMasterGraph.prototype.draw = function() {
......@@ -216,9 +276,9 @@ export const ContributorsMasterGraph = (function(superClass) {
this.process_dates(this.data);
ContributorsGraph.set_y_domain(this.data);
this.set_y_domain();
this.svg.select("path").datum(this.data);
this.svg.select("path").attr("d", this.area);
return this.svg.select(".y.axis").call(this.y_axis);
this.svg.select('path').datum(this.data);
this.svg.select('path').attr('d', this.area);
return this.svg.select('.y.axis').call(this.y_axis);
};
return ContributorsMasterGraph;
......@@ -252,43 +312,58 @@ export const ContributorsAuthorGraph = (function(superClass) {
};
ContributorsAuthorGraph.prototype.create_axes = function() {
this.x_axis = d3.axisBottom()
this.x_axis = d3
.axisBottom()
.scale(this.x)
.ticks(8)
.tickFormat(dateTickFormat);
return this.y_axis = d3.axisLeft().scale(this.y).ticks(5);
return (this.y_axis = d3
.axisLeft()
.scale(this.y)
.ticks(5));
};
ContributorsAuthorGraph.prototype.create_area = function(x, y) {
return this.area = d3.area().x(function(d) {
const parseDate = d3.timeParse("%Y-%m-%d");
return x(parseDate(d));
}).y0(this.height).y1((function(_this) {
return function(d) {
if (_this.data[d] != null) {
return y(_this.data[d]);
} else {
return y(0);
}
};
})(this));
return (this.area = d3
.area()
.x(function(d) {
const parseDate = d3.timeParse('%Y-%m-%d');
return x(parseDate(d));
})
.y0(this.height)
.y1(
(function(_this) {
return function(d) {
if (_this.data[d] != null) {
return y(_this.data[d]);
} else {
return y(0);
}
};
})(this),
));
};
ContributorsAuthorGraph.prototype.create_svg = function() {
const persons = document.querySelectorAll('.person');
this.list_item = persons[persons.length - 1];
this.svg = d3.select(this.list_item)
.append("svg")
.attr("width", this.width + this.MARGIN.left + this.MARGIN.right)
.attr("height", this.height + this.MARGIN.top + this.MARGIN.bottom)
.attr("class", "spark")
.append("g")
.attr("transform", "translate(" + this.MARGIN.left + "," + this.MARGIN.top + ")");
this.svg = d3
.select(this.list_item)
.append('svg')
.attr('width', this.width + this.MARGIN.left + this.MARGIN.right)
.attr('height', this.height + this.MARGIN.top + this.MARGIN.bottom)
.attr('class', 'spark')
.append('g')
.attr('transform', 'translate(' + this.MARGIN.left + ',' + this.MARGIN.top + ')');
return this.svg;
};
ContributorsAuthorGraph.prototype.draw_path = function(data) {
return this.svg.append("path").datum(data).attr("class", "area-contributor").attr("d", this.area);
return this.svg
.append('path')
.datum(data)
.attr('class', 'area-contributor')
.attr('d', this.area);
};
ContributorsAuthorGraph.prototype.draw = function() {
......@@ -304,10 +379,10 @@ export const ContributorsAuthorGraph = (function(superClass) {
ContributorsAuthorGraph.prototype.redraw = function() {
this.set_domain();
this.svg.select("path").datum(this.dates);
this.svg.select("path").attr("d", this.area);
this.svg.select(".x.axis").call(this.x_axis);
return this.svg.select(".y.axis").call(this.y_axis);
this.svg.select('path').datum(this.dates);
this.svg.select('path').attr('d', this.area);
this.svg.select('.x.axis').call(this.x_axis);
return this.svg.select('.y.axis').call(this.y_axis);
};
return ContributorsAuthorGraph;
......
......@@ -26,12 +26,12 @@ export default {
by_author = _.toArray(by_author);
return {
total: total,
by_author: by_author
by_author: by_author,
};
},
add_date: function(date, collection) {
collection[date] = {};
return collection[date].date = date;
return (collection[date].date = date);
},
add_author: function(author, by_author, by_email) {
var data, normalized_email;
......@@ -49,28 +49,28 @@ export default {
return this.store_deletions(entry, total, by_author);
},
store_commits: function(total, by_author) {
this.add(total, "commits", 1);
return this.add(by_author, "commits", 1);
this.add(total, 'commits', 1);
return this.add(by_author, 'commits', 1);
},
add: function(collection, field, value) {
if (collection[field] == null) {
collection[field] = 0;
}
return collection[field] += value;
return (collection[field] += value);
},
store_additions: function(entry, total, by_author) {
if (entry.additions == null) {
entry.additions = 0;
}
this.add(total, "additions", entry.additions);
return this.add(by_author, "additions", entry.additions);
this.add(total, 'additions', entry.additions);
return this.add(by_author, 'additions', entry.additions);
},
store_deletions: function(entry, total, by_author) {
if (entry.deletions == null) {
entry.deletions = 0;
}
this.add(total, "deletions", entry.deletions);
return this.add(by_author, "deletions", entry.deletions);
this.add(total, 'deletions', entry.deletions);
return this.add(by_author, 'deletions', entry.deletions);
},
get_total_data: function(parsed_log, field) {
var log, total_data;
......@@ -95,15 +95,18 @@ export default {
}
log = parsed_log.by_author;
author_data = [];
_.each(log, (function(_this) {
return function(log_entry) {
var parsed_log_entry;
parsed_log_entry = _this.parse_log_entry(log_entry, field, date_range);
if (!_.isEmpty(parsed_log_entry.dates)) {
return author_data.push(parsed_log_entry);
}
};
})(this));
_.each(
log,
(function(_this) {
return function(log_entry) {
var parsed_log_entry;
parsed_log_entry = _this.parse_log_entry(log_entry, field, date_range);
if (!_.isEmpty(parsed_log_entry.dates)) {
return author_data.push(parsed_log_entry);
}
};
})(this),
);
return _.sortBy(author_data, function(d) {
return d[field];
}).reverse();
......@@ -120,16 +123,19 @@ export default {
parsed_entry.additions = 0;
parsed_entry.deletions = 0;
_.each(_.omit(log_entry, 'author_name', 'author_email'), (function(_this) {
return function(value, key) {
if (_this.in_range(value.date, date_range)) {
parsed_entry.dates[value.date] = value[field];
parsed_entry.commits += value.commits;
parsed_entry.additions += value.additions;
return parsed_entry.deletions += value.deletions;
}
};
})(this));
_.each(
_.omit(log_entry, 'author_name', 'author_email'),
(function(_this) {
return function(value, key) {
if (_this.in_range(value.date, date_range)) {
parsed_entry.dates[value.date] = value[field];
parsed_entry.commits += value.commits;
parsed_entry.additions += value.additions;
return (parsed_entry.deletions += value.deletions);
}
};
})(this),
);
return parsed_entry;
},
in_range: function(date, date_range) {
......@@ -139,5 +145,5 @@ export default {
} else {
return false;
}
}
},
};
......@@ -16,7 +16,8 @@ export default () => {
);
const fileBlobPermalinkUrlElement = document.querySelector('.js-data-file-blob-permalink-url');
const fileBlobPermalinkUrl = fileBlobPermalinkUrlElement && fileBlobPermalinkUrlElement.getAttribute('href');
const fileBlobPermalinkUrl =
fileBlobPermalinkUrlElement && fileBlobPermalinkUrlElement.getAttribute('href');
new ShortcutsNavigation(); // eslint-disable-line no-new
......
import ZenMode from '~/zen_mode';
import GLForm from '~/gl_form';
export default function ($formEl) {
export default function($formEl) {
new ZenMode(); // eslint-disable-line no-new
new GLForm($formEl); // eslint-disable-line no-new
}
......@@ -5,7 +5,7 @@ import ZenMode from '~/zen_mode';
import '~/notes/index';
import initIssueableApp from '~/issue_show';
export default function () {
export default function() {
initIssueableApp();
new Issue(); // eslint-disable-line no-new
new ShortcutsIssuable(); // eslint-disable-line no-new
......
<script>
import _ from 'underscore';
import axios from '~/lib/utils/axios_utils';
import createFlash from '~/flash';
import GlModal from '~/vue_shared/components/gl_modal.vue';
import { s__, sprintf } from '~/locale';
import { visitUrl } from '~/lib/utils/url_utility';
import eventHub from '../event_hub';
import _ from 'underscore';
import axios from '~/lib/utils/axios_utils';
import createFlash from '~/flash';
import GlModal from '~/vue_shared/components/gl_modal.vue';
import { s__, sprintf } from '~/locale';
import { visitUrl } from '~/lib/utils/url_utility';
import eventHub from '../event_hub';
export default {
components: {
GlModal,
export default {
components: {
GlModal,
},
props: {
url: {
type: String,
required: true,
},
props: {
url: {
type: String,
required: true,
},
labelTitle: {
type: String,
required: true,
},
labelColor: {
type: String,
required: true,
},
labelTextColor: {
type: String,
required: true,
},
groupName: {
type: String,
required: true,
},
labelTitle: {
type: String,
required: true,
},
computed: {
text() {
return sprintf(s__(`Labels|Promoting %{labelTitle} will make it available for all projects inside %{groupName}.
Existing project labels with the same title will be merged. This action cannot be reversed.`), {
labelColor: {
type: String,
required: true,
},
labelTextColor: {
type: String,
required: true,
},
groupName: {
type: String,
required: true,
},
},
computed: {
text() {
return sprintf(
s__(`Labels|Promoting %{labelTitle} will make it available for all projects inside %{groupName}.
Existing project labels with the same title will be merged. This action cannot be reversed.`),
{
labelTitle: this.labelTitle,
groupName: this.groupName,
});
},
title() {
const label = `<span
},
);
},
title() {
const label = `<span
class="label color-label"
style="background-color: ${this.labelColor}; color: ${this.labelTextColor};"
>${_.escape(this.labelTitle)}</span>`;
return sprintf(s__('Labels|<span>Promote label</span> %{labelTitle} <span>to Group Label?</span>'), {
return sprintf(
s__('Labels|<span>Promote label</span> %{labelTitle} <span>to Group Label?</span>'),
{
labelTitle: label,
}, false);
},
},
false,
);
},
methods: {
onSubmit() {
eventHub.$emit('promoteLabelModal.requestStarted', this.url);
return axios.post(this.url, { params: { format: 'json' } })
.then((response) => {
eventHub.$emit('promoteLabelModal.requestFinished', { labelUrl: this.url, successful: true });
visitUrl(response.data.url);
})
.catch((error) => {
eventHub.$emit('promoteLabelModal.requestFinished', { labelUrl: this.url, successful: false });
createFlash(error);
},
methods: {
onSubmit() {
eventHub.$emit('promoteLabelModal.requestStarted', this.url);
return axios
.post(this.url, { params: { format: 'json' } })
.then(response => {
eventHub.$emit('promoteLabelModal.requestFinished', {
labelUrl: this.url,
successful: true,
});
visitUrl(response.data.url);
})
.catch(error => {
eventHub.$emit('promoteLabelModal.requestFinished', {
labelUrl: this.url,
successful: false,
});
},
createFlash(error);
});
},
};
},
};
</script>
<template>
<gl-modal
......
......@@ -10,20 +10,24 @@ const initLabelIndex = () => {
initLabels();
const onRequestFinished = ({ labelUrl, successful }) => {
const button = document.querySelector(`.js-promote-project-label-button[data-url="${labelUrl}"]`);
const button = document.querySelector(
`.js-promote-project-label-button[data-url="${labelUrl}"]`,
);
if (!successful) {
button.removeAttribute('disabled');
}
};
const onRequestStarted = (labelUrl) => {
const button = document.querySelector(`.js-promote-project-label-button[data-url="${labelUrl}"]`);
const onRequestStarted = labelUrl => {
const button = document.querySelector(
`.js-promote-project-label-button[data-url="${labelUrl}"]`,
);
button.setAttribute('disabled', '');
eventHub.$once('promoteLabelModal.requestFinished', onRequestFinished);
};
const onDeleteButtonClick = (event) => {
const onDeleteButtonClick = event => {
const button = event.currentTarget;
const modalProps = {
labelTitle: button.dataset.labelTitle,
......@@ -37,12 +41,12 @@ const initLabelIndex = () => {
};
const promoteLabelButtons = document.querySelectorAll('.js-promote-project-label-button');
promoteLabelButtons.forEach((button) => {
promoteLabelButtons.forEach(button => {
button.addEventListener('click', onDeleteButtonClick);
});
eventHub.$once('promoteLabelModal.mounted', () => {
promoteLabelButtons.forEach((button) => {
promoteLabelButtons.forEach(button => {
button.removeAttribute('disabled');
});
});
......
......@@ -6,13 +6,15 @@ import BranchGraph from '../../../network/branch_graph';
export default (function() {
function Network(opts) {
var vph;
$("#filter_ref").click(function() {
return $(this).closest('form').submit();
$('#filter_ref').click(function() {
return $(this)
.closest('form')
.submit();
});
this.branch_graph = new BranchGraph($(".network-graph"), opts);
this.branch_graph = new BranchGraph($('.network-graph'), opts);
vph = $(window).height() - 250;
$('.network-graph').css({
'height': vph + 'px'
height: vph + 'px',
});
}
......
import Vue from 'vue';
import PipelineSchedulesCallout from '../shared/components/pipeline_schedules_callout.vue';
document.addEventListener('DOMContentLoaded', () => new Vue({
el: '#pipeline-schedules-callout',
components: {
'pipeline-schedules-callout': PipelineSchedulesCallout,
},
render(createElement) {
return createElement('pipeline-schedules-callout');
},
}));
document.addEventListener(
'DOMContentLoaded',
() =>
new Vue({
el: '#pipeline-schedules-callout',
components: {
'pipeline-schedules-callout': PipelineSchedulesCallout,
},
render(createElement) {
return createElement('pipeline-schedules-callout');
},
}),
);
<script>
import _ from 'underscore';
import _ from 'underscore';
export default {
props: {
initialCronInterval: {
type: String,
required: false,
default: '',
},
},
data() {
return {
inputNameAttribute: 'schedule[cron]',
cronInterval: this.initialCronInterval,
cronIntervalPresets: {
everyDay: '0 4 * * *',
everyWeek: '0 4 * * 0',
everyMonth: '0 4 1 * *',
},
cronSyntaxUrl: 'https://en.wikipedia.org/wiki/Cron',
customInputEnabled: false,
};
export default {
props: {
initialCronInterval: {
type: String,
required: false,
default: '',
},
computed: {
intervalIsPreset() {
return _.contains(this.cronIntervalPresets, this.cronInterval);
},
// The text input is editable when there's a custom interval, or when it's
// a preset interval and the user clicks the 'custom' radio button
isEditable() {
return !!(this.customInputEnabled || !this.intervalIsPreset);
},
data() {
return {
inputNameAttribute: 'schedule[cron]',
cronInterval: this.initialCronInterval,
cronIntervalPresets: {
everyDay: '0 4 * * *',
everyWeek: '0 4 * * 0',
everyMonth: '0 4 1 * *',
},
cronSyntaxUrl: 'https://en.wikipedia.org/wiki/Cron',
customInputEnabled: false,
};
},
computed: {
intervalIsPreset() {
return _.contains(this.cronIntervalPresets, this.cronInterval);
},
watch: {
cronInterval() {
// updates field validation state when model changes, as
// glFieldError only updates on input.
this.$nextTick(() => {
gl.pipelineScheduleFieldErrors.updateFormValidityState();
});
},
// The text input is editable when there's a custom interval, or when it's
// a preset interval and the user clicks the 'custom' radio button
isEditable() {
return !!(this.customInputEnabled || !this.intervalIsPreset);
},
created() {
if (this.intervalIsPreset) {
this.enableCustomInput = false;
}
},
watch: {
cronInterval() {
// updates field validation state when model changes, as
// glFieldError only updates on input.
this.$nextTick(() => {
gl.pipelineScheduleFieldErrors.updateFormValidityState();
});
},
methods: {
toggleCustomInput(shouldEnable) {
this.customInputEnabled = shouldEnable;
},
created() {
if (this.intervalIsPreset) {
this.enableCustomInput = false;
}
},
methods: {
toggleCustomInput(shouldEnable) {
this.customInputEnabled = shouldEnable;
if (shouldEnable) {
// We need to change the value so other radios don't remain selected
// because the model (cronInterval) hasn't changed. The server trims it.
this.cronInterval = `${this.cronInterval} `;
}
},
if (shouldEnable) {
// We need to change the value so other radios don't remain selected
// because the model (cronInterval) hasn't changed. The server trims it.
this.cronInterval = `${this.cronInterval} `;
}
},
};
},
};
</script>
<template>
......
<script>
import Vue from 'vue';
import Cookies from 'js-cookie';
import Translate from '../../../../../vue_shared/translate';
import illustrationSvg from '../icons/intro_illustration.svg';
import Vue from 'vue';
import Cookies from 'js-cookie';
import Translate from '../../../../../vue_shared/translate';
import illustrationSvg from '../icons/intro_illustration.svg';
Vue.use(Translate);
Vue.use(Translate);
const cookieKey = 'pipeline_schedules_callout_dismissed';
const cookieKey = 'pipeline_schedules_callout_dismissed';
export default {
name: 'PipelineSchedulesCallout',
data() {
return {
docsUrl: document.getElementById('pipeline-schedules-callout').dataset.docsUrl,
calloutDismissed: Cookies.get(cookieKey) === 'true',
};
export default {
name: 'PipelineSchedulesCallout',
data() {
return {
docsUrl: document.getElementById('pipeline-schedules-callout').dataset.docsUrl,
calloutDismissed: Cookies.get(cookieKey) === 'true',
};
},
created() {
this.illustrationSvg = illustrationSvg;
},
methods: {
dismissCallout() {
this.calloutDismissed = true;
Cookies.set(cookieKey, this.calloutDismissed, { expires: 365 });
},
created() {
this.illustrationSvg = illustrationSvg;
},
methods: {
dismissCallout() {
this.calloutDismissed = true;
Cookies.set(cookieKey, this.calloutDismissed, { expires: 365 });
},
},
};
},
};
</script>
<template>
<div
......
......@@ -26,8 +26,7 @@ export default class TargetBranchDropdown {
}
formatBranchesList() {
return this.$dropdown.data('data')
.map(val => ({ name: val }));
return this.$dropdown.data('data').map(val => ({ name: val }));
}
setDropdownToggle() {
......
......@@ -11,7 +11,9 @@ Vue.use(Translate);
function initIntervalPatternInput() {
const intervalPatternMount = document.getElementById('interval-pattern-input');
const initialCronInterval = intervalPatternMount ? intervalPatternMount.dataset.initialInterval : '';
const initialCronInterval = intervalPatternMount
? intervalPatternMount.dataset.initialInterval
: '';
return new Vue({
el: intervalPatternMount,
......
......@@ -7,26 +7,29 @@ const options = {
maintainAspectRatio: false,
};
const buildChart = (chartScope) => {
const buildChart = chartScope => {
const data = {
labels: chartScope.labels,
datasets: [{
fillColor: '#707070',
strokeColor: '#707070',
pointColor: '#707070',
pointStrokeColor: '#EEE',
data: chartScope.totalValues,
},
{
fillColor: '#1aaa55',
strokeColor: '#1aaa55',
pointColor: '#1aaa55',
pointStrokeColor: '#fff',
data: chartScope.successValues,
},
datasets: [
{
fillColor: '#707070',
strokeColor: '#707070',
pointColor: '#707070',
pointStrokeColor: '#EEE',
data: chartScope.totalValues,
},
{
fillColor: '#1aaa55',
strokeColor: '#1aaa55',
pointColor: '#1aaa55',
pointStrokeColor: '#fff',
data: chartScope.successValues,
},
],
};
const ctx = $(`#${chartScope.scope}Chart`).get(0).getContext('2d');
const ctx = $(`#${chartScope.scope}Chart`)
.get(0)
.getContext('2d');
new Chart(ctx).Line(data, options);
};
......@@ -36,14 +39,16 @@ document.addEventListener('DOMContentLoaded', () => {
const chartsData = JSON.parse(document.getElementById('pipelinesChartsData').innerHTML);
const data = {
labels: chartTimesData.labels,
datasets: [{
fillColor: 'rgba(220,220,220,0.5)',
strokeColor: 'rgba(220,220,220,1)',
barStrokeWidth: 1,
barValueSpacing: 1,
barDatasetSpacing: 1,
data: chartTimesData.values,
}],
datasets: [
{
fillColor: 'rgba(220,220,220,0.5)',
strokeColor: 'rgba(220,220,220,1)',
barStrokeWidth: 1,
barValueSpacing: 1,
barDatasetSpacing: 1,
data: chartTimesData.values,
},
],
};
if (window.innerWidth < 768) {
......@@ -51,7 +56,11 @@ document.addEventListener('DOMContentLoaded', () => {
options.scaleFontSize = 8;
}
new Chart($('#build_timesChart').get(0).getContext('2d')).Bar(data, options);
new Chart(
$('#build_timesChart')
.get(0)
.getContext('2d'),
).Bar(data, options);
chartsData.forEach(scope => buildChart(scope));
});
......@@ -6,35 +6,39 @@ import { convertPermissionToBoolean } from '../../../../lib/utils/common_utils';
Vue.use(Translate);
document.addEventListener('DOMContentLoaded', () => new Vue({
el: '#pipelines-list-vue',
components: {
pipelinesComponent,
},
data() {
return {
store: new PipelinesStore(),
};
},
created() {
this.dataset = document.querySelector(this.$options.el).dataset;
},
render(createElement) {
return createElement('pipelines-component', {
props: {
store: this.store,
endpoint: this.dataset.endpoint,
helpPagePath: this.dataset.helpPagePath,
emptyStateSvgPath: this.dataset.emptyStateSvgPath,
errorStateSvgPath: this.dataset.errorStateSvgPath,
noPipelinesSvgPath: this.dataset.noPipelinesSvgPath,
autoDevopsPath: this.dataset.helpAutoDevopsPath,
newPipelinePath: this.dataset.newPipelinePath,
canCreatePipeline: convertPermissionToBoolean(this.dataset.canCreatePipeline),
hasGitlabCi: convertPermissionToBoolean(this.dataset.hasGitlabCi),
ciLintPath: this.dataset.ciLintPath,
resetCachePath: this.dataset.resetCachePath,
document.addEventListener(
'DOMContentLoaded',
() =>
new Vue({
el: '#pipelines-list-vue',
components: {
pipelinesComponent,
},
});
},
}));
data() {
return {
store: new PipelinesStore(),
};
},
created() {
this.dataset = document.querySelector(this.$options.el).dataset;
},
render(createElement) {
return createElement('pipelines-component', {
props: {
store: this.store,
endpoint: this.dataset.endpoint,
helpPagePath: this.dataset.helpPagePath,
emptyStateSvgPath: this.dataset.emptyStateSvgPath,
errorStateSvgPath: this.dataset.errorStateSvgPath,
noPipelinesSvgPath: this.dataset.noPipelinesSvgPath,
autoDevopsPath: this.dataset.helpAutoDevopsPath,
newPipelinePath: this.dataset.newPipelinePath,
canCreatePipeline: convertPermissionToBoolean(this.dataset.canCreatePipeline),
hasGitlabCi: convertPermissionToBoolean(this.dataset.hasGitlabCi),
ciLintPath: this.dataset.ciLintPath,
resetCachePath: this.dataset.resetCachePath,
},
});
},
}),
);
......@@ -2,9 +2,12 @@ import Pipelines from '~/pipelines';
export default () => {
const { controllerAction } = document.querySelector('.js-pipeline-container').dataset;
const pipelineStatusUrl = `${document.querySelector('.js-pipeline-tab-link a').getAttribute('href')}/status.json`;
const pipelineStatusUrl = `${document
.querySelector('.js-pipeline-tab-link a')
.getAttribute('href')}/status.json`;
new Pipelines({ // eslint-disable-line no-new
// eslint-disable-next-line no-new
new Pipelines({
initTabs: true,
pipelineStatusUrl,
tabsOptions: {
......
<script>
import projectFeatureToggle from '../../../../../vue_shared/components/toggle_button.vue';
import projectFeatureToggle from '../../../../../vue_shared/components/toggle_button.vue';
export default {
components: {
projectFeatureToggle,
},
export default {
components: {
projectFeatureToggle,
},
model: {
prop: 'value',
event: 'change',
},
model: {
prop: 'value',
event: 'change',
},
props: {
name: {
type: String,
required: false,
default: '',
},
options: {
type: Array,
required: false,
default: () => [],
},
value: {
type: Number,
required: false,
default: 0,
},
disabledInput: {
type: Boolean,
required: false,
default: false,
},
props: {
name: {
type: String,
required: false,
default: '',
},
options: {
type: Array,
required: false,
default: () => [],
},
value: {
type: Number,
required: false,
default: 0,
},
disabledInput: {
type: Boolean,
required: false,
default: false,
},
},
computed: {
featureEnabled() {
return this.value !== 0;
},
computed: {
featureEnabled() {
return this.value !== 0;
},
displayOptions() {
if (this.featureEnabled) {
return this.options;
}
return [
[0, 'Enable feature to choose access level'],
];
},
displayOptions() {
if (this.featureEnabled) {
return this.options;
}
return [[0, 'Enable feature to choose access level']];
},
displaySelectInput() {
return this.disabledInput || !this.featureEnabled || this.displayOptions.length < 2;
},
displaySelectInput() {
return this.disabledInput || !this.featureEnabled || this.displayOptions.length < 2;
},
},
methods: {
toggleFeature(featureEnabled) {
if (featureEnabled === false || this.options.length < 1) {
this.$emit('change', 0);
} else {
const [firstOptionValue] = this.options[this.options.length - 1];
this.$emit('change', firstOptionValue);
}
},
methods: {
toggleFeature(featureEnabled) {
if (featureEnabled === false || this.options.length < 1) {
this.$emit('change', 0);
} else {
const [firstOptionValue] = this.options[this.options.length - 1];
this.$emit('change', firstOptionValue);
}
},
selectOption(e) {
this.$emit('change', Number(e.target.value));
},
selectOption(e) {
this.$emit('change', Number(e.target.value));
},
};
},
};
</script>
<template>
......
<script>
export default {
props: {
label: {
type: String,
required: false,
default: null,
},
helpPath: {
type: String,
required: false,
default: null,
},
helpText: {
type: String,
required: false,
default: null,
},
export default {
props: {
label: {
type: String,
required: false,
default: null,
},
};
helpPath: {
type: String,
required: false,
default: null,
},
helpText: {
type: String,
required: false,
default: null,
},
},
};
</script>
<template>
......
......@@ -5,7 +5,9 @@ export const visibilityOptions = {
};
export const visibilityLevelDescriptions = {
[visibilityOptions.PRIVATE]: 'The project is accessible only by members of the project. Access must be granted explicitly to each user.',
[visibilityOptions.PRIVATE]:
'The project is accessible only by members of the project. Access must be granted explicitly to each user.',
[visibilityOptions.INTERNAL]: 'The project can be accessed by any user who is logged in.',
[visibilityOptions.PUBLIC]: 'The project can be accessed by anyone, regardless of authentication.',
[visibilityOptions.PUBLIC]:
'The project can be accessed by anyone, regardless of authentication.',
};
......@@ -8,8 +8,9 @@ export default function projectAvatar() {
$('.js-project-avatar-input').bind('change', function onClickAvatarInput() {
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);
});
}
......@@ -21,7 +21,8 @@ document.addEventListener('DOMContentLoaded', () => {
const { deleteWikiUrl, pageTitle } = deleteWikiModalWrapperEl.dataset;
new Vue({ // eslint-disable-line no-new
// eslint-disable-next-line no-new
new Vue({
el: deleteWikiModalWrapperEl,
data: {
deleteWikiUrl: '',
......
......@@ -22,7 +22,7 @@ export default class Search {
fields: ['full_name'],
},
data(term, callback) {
return Api.groups(term, {}, (data) => {
return Api.groups(term, {}, data => {
data.unshift({
full_name: 'Any',
});
......@@ -37,7 +37,7 @@ export default class Search {
return obj.full_name;
},
toggleLabel(obj) {
return `${($groupDropdown.data('defaultLabel'))} ${obj.full_name}`;
return `${$groupDropdown.data('defaultLabel')} ${obj.full_name}`;
},
clicked: () => Search.submitSearch(),
});
......@@ -52,7 +52,7 @@ export default class Search {
},
data: (term, callback) => {
this.getProjectsData(term)
.then((data) => {
.then(data => {
data.unshift({
name_with_namespace: 'Any',
});
......@@ -70,7 +70,7 @@ export default class Search {
return obj.name_with_namespace;
},
toggleLabel(obj) {
return `${($projectDropdown.data('defaultLabel'))} ${obj.name_with_namespace}`;
return `${$projectDropdown.data('defaultLabel')} ${obj.name_with_namespace}`;
},
clicked: () => Search.submitSearch(),
});
......@@ -99,17 +99,24 @@ export default class Search {
}
clearSearchField() {
return $(this.searchInput).val('').trigger('keyup').focus();
return $(this.searchInput)
.val('')
.trigger('keyup')
.focus();
}
getProjectsData(term) {
return new Promise((resolve) => {
return new Promise(resolve => {
if (this.groupId) {
Api.groupProjects(this.groupId, term, {}, resolve);
} else {
Api.projects(term, {
order_by: 'id',
}, resolve);
Api.projects(
term,
{
order_by: 'id',
},
resolve,
);
}
});
}
......
......@@ -20,7 +20,7 @@ export default class SigninTabsMemoizer {
bootstrap() {
const tabs = document.querySelectorAll(this.tabSelector);
if (tabs.length > 0) {
tabs[0].addEventListener('click', (e) => {
tabs[0].addEventListener('click', e => {
if (e.target && e.target.nodeName === 'A') {
const anchorName = e.target.getAttribute('href');
this.saveData(anchorName);
......
......@@ -22,10 +22,10 @@ export default class UsernameValidator {
available: false,
valid: false,
pending: false,
empty: true
empty: true,
};
const debounceTimeout = _.debounce((username) => {
const debounceTimeout = _.debounce(username => {
this.validateUsername(username);
}, debounceTimeoutDuration);
......@@ -81,7 +81,8 @@ export default class UsernameValidator {
this.state.pending = true;
this.state.available = false;
this.renderState();
axios.get(`${gon.relative_url_root}/users/${username}/exists`)
axios
.get(`${gon.relative_url_root}/users/${username}/exists`)
.then(({ data }) => this.setAvailabilityState(data.exists))
.catch(() => flash(__('An error occurred while validating username')));
}
......@@ -100,8 +101,7 @@ export default class UsernameValidator {
clearFieldValidationState() {
this.inputElement.siblings('p').hide();
this.inputElement.removeClass(invalidInputClass)
.removeClass(successInputClass);
this.inputElement.removeClass(invalidInputClass).removeClass(successInputClass);
}
setUnavailableState() {
......
......@@ -13,10 +13,12 @@ function initUserProfile(action) {
new UserTabs({ parentEl: '.user-profile', action });
// hide project limit message
$('.hide-project-limit-message').on('click', (e) => {
$('.hide-project-limit-message').on('click', e => {
e.preventDefault();
Cookies.set('hide_project_limit_message', 'false');
$(this).parents('.project-limit-message').remove();
$(this)
.parents('.project-limit-message')
.remove();
});
}
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment