Commit 3cab2087 authored by Mike Greiling's avatar Mike Greiling

Run all ee-specific files through prettier

parent b09b82f1
<script>
import Flash from '~/flash';
import { redirectTo } from '~/lib/utils/url_utility';
import Flash from '~/flash';
import { redirectTo } from '~/lib/utils/url_utility';
import GitlabSlackService from '../services/gitlab_slack_service';
import GitlabSlackService from '../services/gitlab_slack_service';
export default {
export default {
props: {
projects: {
type: Array,
......@@ -80,7 +80,7 @@
.catch(() => Flash('Unable to build Slack link.'));
},
},
};
};
</script>
<template>
......
......@@ -2,7 +2,10 @@ import $ from 'jquery';
import _ from 'underscore';
export default () => {
$('.approver-list').on('click', '.unsaved-approvers.approver .btn-remove', function approverListClickCallback(ev) {
$('.approver-list').on(
'click',
'.unsaved-approvers.approver .btn-remove',
function approverListClickCallback(ev) {
const removeElement = $(this).closest('li');
const approverId = parseInt(removeElement.attr('id').replace('user_', ''), 10);
const approverIds = $('input#merge_request_approver_ids');
......@@ -16,9 +19,13 @@ export default () => {
}
ev.preventDefault();
});
},
);
$('.approver-list').on('click', '.unsaved-approvers.approver-group .btn-remove', function approverListRemoveClickCallback(ev) {
$('.approver-list').on(
'click',
'.unsaved-approvers.approver-group .btn-remove',
function approverListRemoveClickCallback(ev) {
const removeElement = $(this).closest('li');
const approverGroupId = parseInt(removeElement.attr('id').replace('group_', ''), 10);
const approverGroupIds = $('input#merge_request_approver_group_ids');
......@@ -32,18 +39,23 @@ export default () => {
}
ev.preventDefault();
});
},
);
$('form.merge-request-form').on('submit', function mergeRequestFormSubmitCallback() {
if ($('input#merge_request_approver_ids').length) {
let approverIds = $.map($('li.unsaved-approvers.approver').not('.approver-template'), li => li.id.replace('user_', ''));
let approverIds = $.map($('li.unsaved-approvers.approver').not('.approver-template'), li =>
li.id.replace('user_', ''),
);
const approversInput = $(this).find('input#merge_request_approver_ids');
approverIds = approverIds.concat(approversInput.val().split(','));
approversInput.val(_.compact(approverIds).join(','));
}
if ($('input#merge_request_approver_group_ids').length) {
let approverGroupIds = $.map($('li.unsaved-approvers.approver-group'), li => li.id.replace('group_', ''));
let approverGroupIds = $.map($('li.unsaved-approvers.approver-group'), li =>
li.id.replace('group_', ''),
);
const approverGroupsInput = $(this).find('input#merge_request_approver_group_ids');
approverGroupIds = approverGroupIds.concat(approverGroupsInput.val().split(','));
approverGroupsInput.val(_.compact(approverGroupIds).join(','));
......@@ -58,9 +70,11 @@ export default () => {
return false;
}
const approverItemHTML = $('.unsaved-approvers.approver-template').clone()
const approverItemHTML = $('.unsaved-approvers.approver-template')
.clone()
.removeClass('hide approver-template')[0]
.outerHTML.replace(/\{approver_name\}/g, username).replace(/\{user_id\}/g, userId);
.outerHTML.replace(/\{approver_name\}/g, username)
.replace(/\{user_id\}/g, userId);
$('.no-approvers').remove();
$('.approver-list').append(approverItemHTML);
......
import BoardsListSelector from './boards_list_selector/index';
export default function () {
export default function() {
const $addListEl = document.querySelector('#js-add-list');
return new BoardsListSelector({
propsData: {
......
......@@ -20,8 +20,8 @@ export default Board.extend({
}
const { issuesSize, totalWeight } = this.list;
return sprintf(__(
`${n__('%d issue', '%d issues', issuesSize)} with %{totalWeight} total weight`),
return sprintf(
__(`${n__('%d issue', '%d issues', issuesSize)} with %{totalWeight} total weight`),
{
totalWeight,
},
......
......@@ -43,15 +43,17 @@ export default Vue.extend({
})
.catch(() => {
this.loading = false;
Flash(sprintf(__('Something went wrong while fetching %{listType} list'), {
Flash(
sprintf(__('Something went wrong while fetching %{listType} list'), {
listType: this.listType,
}));
}),
);
});
},
filterItems(term, items) {
const query = term.toLowerCase();
return items.filter((item) => {
return items.filter(item => {
const name = item.name ? item.name.toLowerCase() : item.title.toLowerCase();
const foundName = name.indexOf(query) > -1;
......
......@@ -31,7 +31,7 @@ export default {
if (!this.query) return this.items;
const query = this.query.toLowerCase();
return this.items.filter((item) => {
return this.items.filter(item => {
const name = item.name ? item.name.toLowerCase() : item.title.toLowerCase();
if (this.listType === 'milestones') {
......
......@@ -140,8 +140,7 @@ export default Vue.extend({
handleDropdownTabClick(e) {
const $addListEl = $('#js-add-list');
$addListEl.data('preventClose', true);
if (e.target.dataset.action === 'tab-assignees' &&
!this.hasAssigneesListMounted) {
if (e.target.dataset.action === 'tab-assignees' && !this.hasAssigneesListMounted) {
this.assigneeList = AssigneeList();
this.hasAssigneesListMounted = true;
}
......
import BoardsListSelector from './boards_list_selector';
export default function () {
export default function() {
const $addListEl = document.querySelector('#js-add-list');
return new BoardsListSelector({
propsData: {
......
<script>
import MilestoneSelect from '~/milestone_select';
import MilestoneSelect from '~/milestone_select';
const ANY_MILESTONE = 'Any Milestone';
const NO_MILESTONE = 'No Milestone';
const ANY_MILESTONE = 'Any Milestone';
const NO_MILESTONE = 'No Milestone';
export default {
export default {
props: {
board: {
type: Object,
......@@ -61,7 +61,7 @@
};
},
},
};
};
</script>
<template>
......
<script>
/* eslint-disable vue/require-default-prop */
/* eslint-disable vue/require-default-prop */
import WeightSelect from 'ee/weight_select';
import WeightSelect from 'ee/weight_select';
const ANY_WEIGHT = 'Any Weight';
const NO_WEIGHT = 'No Weight';
const ANY_WEIGHT = 'Any Weight';
const NO_WEIGHT = 'No Weight';
export default {
export default {
props: {
board: {
type: Object,
......@@ -65,7 +65,7 @@
return -1;
},
},
};
};
</script>
<template>
......
......@@ -19,7 +19,8 @@ const d3 = {
axisLeft,
line,
transition,
easeLinear };
easeLinear,
};
const margin = { top: 5, right: 65, bottom: 30, left: 50 };
// const parseDate = d3.timeFormat('%Y-%m-%d');
const bisectDate = d3.bisector(d => d.date).left;
......@@ -28,7 +29,9 @@ const tooltipDistance = 15;
export default class BurndownChart {
constructor({ container, startDate, dueDate }) {
this.canvas = d3.select(container).append('svg')
this.canvas = d3
.select(container)
.append('svg')
.attr('height', '100%')
.attr('width', '100%');
......@@ -56,21 +59,35 @@ export default class BurndownChart {
this.chartLegendIdealKey = this.chartLegendGroup.append('g');
this.chartLegendIdealKey.append('line').attr('class', 'ideal line');
this.chartLegendIdealKey.append('text').text('Guideline');
this.chartLegendIdealKeyBBox = this.chartLegendIdealKey.select('text').node().getBBox();
this.chartLegendIdealKeyBBox = this.chartLegendIdealKey
.select('text')
.node()
.getBBox();
this.chartLegendActualKey = this.chartLegendGroup.append('g');
this.chartLegendActualKey.append('line').attr('class', 'actual line');
this.chartLegendActualKey.append('text').text('Progress');
this.chartLegendActualKeyBBox = this.chartLegendActualKey.select('text').node().getBBox();
this.chartLegendActualKeyBBox = this.chartLegendActualKey
.select('text')
.node()
.getBBox();
// create tooltips
this.chartFocus = this.chartGroup.append('g').attr('class', 'focus').style('display', 'none');
this.chartFocus = this.chartGroup
.append('g')
.attr('class', 'focus')
.style('display', 'none');
this.chartFocus.append('circle').attr('r', 4);
this.tooltipGroup = this.chartFocus.append('g').attr('class', 'chart-tooltip');
this.tooltipGroup.append('rect').attr('rx', 3).attr('ry', 3);
this.tooltipGroup
.append('rect')
.attr('rx', 3)
.attr('ry', 3);
this.tooltipGroup.append('text');
this.chartOverlay = this.chartGroup.append('rect').attr('class', 'overlay')
this.chartOverlay = this.chartGroup
.append('rect')
.attr('class', 'overlay')
.on('mouseover', () => this.chartFocus.style('display', null))
.on('mouseout', () => this.chartFocus.style('display', 'none'))
.on('mousemove', () => this.handleMousemove());
......@@ -91,28 +108,33 @@ export default class BurndownChart {
this.yMax = 1;
// create scales
this.xScale = d3.scaleTime()
this.xScale = d3
.scaleTime()
.range([0, this.chartWidth])
.domain([this.startDate, this.xMax]);
this.yScale = d3.scaleLinear()
this.yScale = d3
.scaleLinear()
.range([this.chartHeight, 0])
.domain([0, this.yMax]);
// create axes
this.xAxis = d3.axisBottom()
this.xAxis = d3
.axisBottom()
.scale(this.xScale)
.tickFormat(d3.timeFormat('%b %-d'))
.tickPadding(6)
.tickSize(4, 0);
this.yAxis = d3.axisLeft()
this.yAxis = d3
.axisLeft()
.scale(this.yScale)
.tickPadding(6)
.tickSize(4, 0);
// create lines
this.line = d3.line()
this.line = d3
.line()
.x(d => this.xScale(new Date(d.date)))
.y(d => this.yScale(d.value));
......@@ -122,10 +144,12 @@ export default class BurndownChart {
// set data and force re-render
setData(data, { label = 'Remaining', animate } = {}) {
this.data = data.map(datum => ({
this.data = data
.map(datum => ({
date: new Date(datum[0]),
value: parseInt(datum[1], 10),
})).sort((a, b) => (a.date - b.date));
}))
.sort((a, b) => a.date - b.date);
// adjust axis domain to correspond with data
this.xMax = Math.max(d3.max(this.data, d => d.date) || 0, this.dueDate);
......@@ -138,7 +162,10 @@ export default class BurndownChart {
// (this must be done here to prevent layout thrashing)
if (this.label !== label) {
this.label = label;
this.yAxisLabelBBox = this.yAxisLabelText.text(label).node().getBBox();
this.yAxisLabelBBox = this.yAxisLabelText
.text(label)
.node()
.getBBox();
}
// set ideal line data
......@@ -206,15 +233,18 @@ export default class BurndownChart {
// replace x-axis line with one which continues into the right margin
this.xAxisGroup.select('.domain').remove();
this.xAxisGroup.select('.domain-line').attr('x1', 0).attr('x2', this.chartWidth + margin.right);
this.xAxisGroup
.select('.domain-line')
.attr('x1', 0)
.attr('x2', this.chartWidth + margin.right);
// update y-axis label
const axisLabelOffset = (this.yAxisLabelBBox.height / 2) - margin.left;
const axisLabelOffset = this.yAxisLabelBBox.height / 2 - margin.left;
const axisLabelPadding = (this.chartHeight - this.yAxisLabelBBox.width - 10) / 2;
this.yAxisLabelText
.attr('y', 0 - margin.left)
.attr('x', 0 - (this.chartHeight / 2))
.attr('x', 0 - this.chartHeight / 2)
.attr('dy', '1em')
.style('text-anchor', 'middle')
.attr('transform', 'rotate(-90)');
......@@ -240,18 +270,21 @@ export default class BurndownChart {
const idealKeyOffset = legendPadding;
const actualKeyOffset = legendPadding + keyHeight + legendSpacing;
const legendWidth = (legendPadding * 2) + 24 + keyWidth;
const legendHeight = (legendPadding * 2) + (keyHeight * 2) + legendSpacing;
const legendOffset = (this.chartWidth + margin.right) - legendWidth - 1;
const legendWidth = legendPadding * 2 + 24 + keyWidth;
const legendHeight = legendPadding * 2 + keyHeight * 2 + legendSpacing;
const legendOffset = this.chartWidth + margin.right - legendWidth - 1;
this.chartLegendGroup.select('rect')
this.chartLegendGroup
.select('rect')
.attr('width', legendWidth)
.attr('height', legendHeight);
this.chartLegendGroup.selectAll('text')
this.chartLegendGroup
.selectAll('text')
.attr('x', 24)
.attr('dy', '1em');
this.chartLegendGroup.selectAll('line')
this.chartLegendGroup
.selectAll('line')
.attr('y1', keyHeight / 2)
.attr('y2', keyHeight / 2)
.attr('x1', 0)
......@@ -298,15 +331,19 @@ export default class BurndownChart {
const x = this.xScale(datum.date);
const y = this.yScale(datum.value);
const textSize = this.tooltipGroup.select('text').text(tooltip).node().getBBox();
const width = textSize.width + (tooltipPadding.x * 2);
const height = textSize.height + (tooltipPadding.y * 2);
const textSize = this.tooltipGroup
.select('text')
.text(tooltip)
.node()
.getBBox();
const width = textSize.width + tooltipPadding.x * 2;
const height = textSize.height + tooltipPadding.y * 2;
// calculate bounraries
const xMin = 0 - x - margin.left;
const yMin = 0 - y - margin.top;
const xMax = (this.chartWidth + margin.right) - x - width;
const yMax = (this.chartHeight + margin.bottom) - y - height;
const xMax = this.chartWidth + margin.right - x - width;
const yMax = this.chartHeight + margin.bottom - y - height;
// try to fit tooltip above point
let xOffset = 0 - Math.floor(width / 2);
......@@ -331,12 +368,14 @@ export default class BurndownChart {
this.chartFocus.attr('transform', `translate(${x}, ${y})`);
this.tooltipGroup.attr('transform', `translate(${xOffset}, ${yOffset})`);
this.tooltipGroup.select('text')
this.tooltipGroup
.select('text')
.attr('dy', '1em')
.attr('x', tooltipPadding.x)
.attr('y', tooltipPadding.y);
this.tooltipGroup.select('rect')
this.tooltipGroup
.select('rect')
.attr('width', width)
.attr('height', height);
}
......@@ -357,7 +396,10 @@ export default class BurndownChart {
static animateLinePath(path, duration = 1000, cb) {
const lineLength = path.node().getTotalLength();
const linearTransition = d3.transition().duration(duration).ease(d3.easeLinear);
const linearTransition = d3
.transition()
.duration(duration)
.ease(d3.easeLinear);
path
.attr('stroke-dasharray', `${lineLength} ${lineLength}`)
.attr('stroke-dashoffset', lineLength)
......
......@@ -31,7 +31,10 @@ export default () => {
const show = $this.data('show');
if (currentView !== show) {
currentView = show;
$this.addClass('active').siblings().removeClass('active');
$this
.addClass('active')
.siblings()
.removeClass('active');
switch (show) {
case 'count':
chart.setData(openIssuesCount, { label: 'Open issues', animate: true });
......
<script>
/**
/**
* Renders a deploy board.
*
* A deploy board is composed by:
......@@ -8,13 +8,13 @@
* - Button Actions.
* [Mockup](https://gitlab.com/gitlab-org/gitlab-ce/uploads/2f655655c0eadf655d0ae7467b53002a/environments__deploy-graphic.png)
*/
import _ from 'underscore';
import { n__ } from '~/locale';
import tooltip from '~/vue_shared/directives/tooltip';
import deployBoardSvg from 'ee_empty_states/icons/_deploy_board.svg';
import instanceComponent from './deploy_board_instance_component.vue';
import _ from 'underscore';
import { n__ } from '~/locale';
import tooltip from '~/vue_shared/directives/tooltip';
import deployBoardSvg from 'ee_empty_states/icons/_deploy_board.svg';
import instanceComponent from './deploy_board_instance_component.vue';
export default {
export default {
components: {
instanceComponent,
},
......@@ -73,7 +73,7 @@
return deployBoardSvg;
},
},
};
};
</script>
<template>
<div class="js-deploy-board deploy-board">
......
<script>
/**
/**
* An instance in deploy board is represented by a square in this mockup:
* https://gitlab.com/gitlab-org/gitlab-ce/uploads/2f655655c0eadf655d0ae7467b53002a/environments__deploy-graphic.png
*
......@@ -12,9 +12,9 @@
* this information in the tooltip and the colors.
* Mockup is https://gitlab.com/gitlab-org/gitlab-ee/merge_requests/1551#note_26595150
*/
import tooltip from '~/vue_shared/directives/tooltip';
import tooltip from '~/vue_shared/directives/tooltip';
export default {
export default {
directives: {
tooltip,
},
......@@ -71,7 +71,7 @@
return `${this.logsPath}?pod_name=${this.podName}`;
},
},
};
};
</script>
<template>
<a
......
<script>
import $ from 'jquery';
import userAvatarLink from '~/vue_shared/components/user_avatar/user_avatar_link.vue';
import timeagoTooltip from '~/vue_shared/components/time_ago_tooltip.vue';
import Icon from '~/vue_shared/components/icon.vue';
import LoadingButton from '~/vue_shared/components/loading_button.vue';
import tooltip from '~/vue_shared/directives/tooltip';
import { __, s__ } from '~/locale';
import eventHub from '../../event_hub';
import { stateEvent } from '../../constants';
import $ from 'jquery';
import userAvatarLink from '~/vue_shared/components/user_avatar/user_avatar_link.vue';
import timeagoTooltip from '~/vue_shared/components/time_ago_tooltip.vue';
import Icon from '~/vue_shared/components/icon.vue';
import LoadingButton from '~/vue_shared/components/loading_button.vue';
import tooltip from '~/vue_shared/directives/tooltip';
import { __, s__ } from '~/locale';
import eventHub from '../../event_hub';
import { stateEvent } from '../../constants';
export default {
export default {
name: 'EpicHeader',
directives: {
tooltip,
......@@ -54,7 +54,9 @@
return this.isEpicOpen ? __('Open') : __('Closed');
},
actionButtonClass() {
return `btn btn-grouped js-btn-epic-action qa-close-reopen-epic-button ${this.isEpicOpen ? 'btn-close' : 'btn-open'}`;
return `btn btn-grouped js-btn-epic-action qa-close-reopen-epic-button ${
this.isEpicOpen ? 'btn-close' : 'btn-open'
}`;
},
actionButtonText() {
return this.isEpicOpen ? __('Close epic') : __('Reopen epic');
......@@ -68,7 +70,8 @@
},
methods: {
deleteEpic() {
if (window.confirm(s__('Epic will be removed! Are you sure?'))) { // eslint-disable-line no-alert
if (window.confirm(s__('Epic will be removed! Are you sure?'))) {
// eslint-disable-line no-alert
this.deleteLoading = true;
this.$emit('deleteEpic');
}
......@@ -81,7 +84,7 @@
this.$emit('toggleEpicStatus', this.isEpicOpen ? stateEvent.close : stateEvent.reopen);
},
},
};
};
</script>
<template>
......
......@@ -7,7 +7,9 @@ export default class SidebarContext {
constructor() {
const $issuableSidebar = $('.js-issuable-update');
Mousetrap.bind('l', () => SidebarContext.openSidebarDropdown($issuableSidebar.find('.js-labels-block')));
Mousetrap.bind('l', () =>
SidebarContext.openSidebarDropdown($issuableSidebar.find('.js-labels-block')),
);
$issuableSidebar
.off('click', '.js-sidebar-dropdown-toggle')
......
<script>
import Flash from '~/flash';
import { visitUrl } from '~/lib/utils/url_utility';
import { s__ } from '~/locale';
import loadingButton from '~/vue_shared/components/loading_button.vue';
import NewEpicService from '../services/new_epic_service';
import Flash from '~/flash';
import { visitUrl } from '~/lib/utils/url_utility';
import { s__ } from '~/locale';
import loadingButton from '~/vue_shared/components/loading_button.vue';
import NewEpicService from '../services/new_epic_service';
export default {
export default {
name: 'NewEpic',
components: {
loadingButton,
......@@ -39,7 +39,8 @@
methods: {
createEpic() {
this.creating = true;
this.service.createEpic(this.title)
this.service
.createEpic(this.title)
.then(({ data }) => {
visitUrl(data.web_url);
})
......@@ -55,7 +56,7 @@
}, 25);
},
},
};
};
</script>
<template>
......
......@@ -7,12 +7,14 @@ export default () => {
if (el) {
const props = el.dataset;
new Vue({ // eslint-disable-line no-new
new Vue({
// eslint-disable-line no-new
el,
components: {
'new-epic-app': NewEpicApp,
},
render: createElement => createElement('new-epic-app', {
render: createElement =>
createElement('new-epic-app', {
props,
}),
});
......
......@@ -119,7 +119,9 @@ export default {
},
popoverOptions() {
return this.getPopoverConfig({
title: s__('Epics|These dates affect how your epics appear in the roadmap. Dates from milestones come from the milestones assigned to issues in the epic. You can also set fixed dates or remove them entirely.'),
title: s__(
'Epics|These dates affect how your epics appear in the roadmap. Dates from milestones come from the milestones assigned to issues in the epic. You can also set fixed dates or remove them entirely.',
),
content: `
<a
href="${gon.gitlab_url}/help/user/group/epics/index.md#start-date-and-due-date"
......@@ -304,4 +306,3 @@ export default {
</div>
</div>
</template>
<script>
import Participants from '~/sidebar/components/participants/participants.vue';
import Participants from '~/sidebar/components/participants/participants.vue';
export default {
export default {
components: {
Participants,
},
......@@ -16,7 +16,7 @@
this.$emit('toggleCollapse');
},
},
};
};
</script>
<template>
......
<script>
import Subscriptions from '~/sidebar/components/subscriptions/subscriptions.vue';
import Subscriptions from '~/sidebar/components/subscriptions/subscriptions.vue';
export default {
export default {
components: {
Subscriptions,
},
......@@ -23,7 +23,7 @@
this.$emit('toggleCollapse');
},
},
};
};
</script>
<template>
......
<script>
import { __, s__ } from '~/locale';
import eventHub from '../event_hub';
import { NODE_ACTIONS } from '../constants';
import Icon from '~/vue_shared/components/icon.vue';
import { __, s__ } from '~/locale';
import eventHub from '../event_hub';
import { NODE_ACTIONS } from '../constants';
import Icon from '~/vue_shared/components/icon.vue';
export default {
export default {
components: {
Icon,
},
......@@ -59,7 +59,7 @@
eventHub.$emit('repairNode', this.node);
},
},
};
};
</script>
<template>
......
<script>
import { s__ } from '~/locale';
import popover from '~/vue_shared/directives/popover';
import tooltip from '~/vue_shared/directives/tooltip';
import Icon from '~/vue_shared/components/icon.vue';
import StackedProgressBar from '~/vue_shared/components/stacked_progress_bar.vue';
import { s__ } from '~/locale';
import popover from '~/vue_shared/directives/popover';
import tooltip from '~/vue_shared/directives/tooltip';
import Icon from '~/vue_shared/components/icon.vue';
import StackedProgressBar from '~/vue_shared/components/stacked_progress_bar.vue';
import { VALUE_TYPE, CUSTOM_TYPE } from '../constants';
import { VALUE_TYPE, CUSTOM_TYPE } from '../constants';
import GeoNodeSyncSettings from './geo_node_sync_settings.vue';
import GeoNodeEventStatus from './geo_node_event_status.vue';
import GeoNodeSyncSettings from './geo_node_sync_settings.vue';
import GeoNodeEventStatus from './geo_node_event_status.vue';
export default {
export default {
components: {
Icon,
StackedProgressBar,
......@@ -117,7 +117,7 @@
};
},
},
};
};
</script>
<template>
......
<script>
/* eslint-disable vue/no-side-effects-in-computed-properties */
import { s__ } from '~/locale';
/* eslint-disable vue/no-side-effects-in-computed-properties */
import { s__ } from '~/locale';
import NodeDetailsSectionMain from './node_detail_sections/node_details_section_main.vue';
import NodeDetailsSectionSync from './node_detail_sections/node_details_section_sync.vue';
import NodeDetailsSectionVerification from './node_detail_sections/node_details_section_verification.vue';
import NodeDetailsSectionOther from './node_detail_sections/node_details_section_other.vue';
import NodeDetailsSectionMain from './node_detail_sections/node_details_section_main.vue';
import NodeDetailsSectionSync from './node_detail_sections/node_details_section_sync.vue';
import NodeDetailsSectionVerification from './node_detail_sections/node_details_section_verification.vue';
import NodeDetailsSectionOther from './node_detail_sections/node_details_section_other.vue';
export default {
export default {
components: {
NodeDetailsSectionMain,
NodeDetailsSectionSync,
......@@ -46,15 +46,17 @@
return !this.nodeDetails.healthy;
},
hasVersionMismatch() {
if (this.nodeDetails.version !== this.nodeDetails.primaryVersion ||
this.nodeDetails.revision !== this.nodeDetails.primaryRevision) {
if (
this.nodeDetails.version !== this.nodeDetails.primaryVersion ||
this.nodeDetails.revision !== this.nodeDetails.primaryRevision
) {
this.errorMessage = s__('GeoNodes|GitLab version does not match the primary node version');
return true;
}
return false;
},
},
};
};
</script>
<template>
......
<script>
import { formatDate } from '~/lib/utils/datetime_utility';
import timeAgoMixin from '~/vue_shared/mixins/timeago';
import tooltip from '~/vue_shared/directives/tooltip';
import { formatDate } from '~/lib/utils/datetime_utility';
import timeAgoMixin from '~/vue_shared/mixins/timeago';
import tooltip from '~/vue_shared/directives/tooltip';
export default {
export default {
directives: {
tooltip,
},
mixins: [
timeAgoMixin,
],
mixins: [timeAgoMixin],
props: {
eventId: {
type: Number,
......@@ -37,7 +35,7 @@
return this.eventId;
},
},
};
};
</script>
<template>
......
<script>
import { s__ } from '~/locale';
import icon from '~/vue_shared/components/icon.vue';
import tooltip from '~/vue_shared/directives/tooltip';
import { s__ } from '~/locale';
import icon from '~/vue_shared/components/icon.vue';
import tooltip from '~/vue_shared/directives/tooltip';
export default {
export default {
components: {
icon,
},
......@@ -56,10 +56,12 @@
if (this.nodeDetailsFailed) {
return '';
}
return s__('GeoNodes|You have configured Geo nodes using an insecure HTTP connection. We recommend the use of HTTPS.');
return s__(
'GeoNodes|You have configured Geo nodes using an insecure HTTP connection. We recommend the use of HTTPS.',
);
},
},
};
};
</script>
<template>
......
<script>
import icon from '~/vue_shared/components/icon.vue';
import { HEALTH_STATUS_ICON } from '../constants';
import icon from '~/vue_shared/components/icon.vue';
import { HEALTH_STATUS_ICON } from '../constants';
export default {
export default {
components: {
icon,
},
......@@ -20,7 +20,7 @@
return HEALTH_STATUS_ICON[this.status.toLowerCase()];
},
},
};
};
</script>
<template>
......
<script>
import { s__ } from '~/locale';
import { timeIntervalInWords } from '~/lib/utils/datetime_utility';
import tooltip from '~/vue_shared/directives/tooltip';
import icon from '~/vue_shared/components/icon.vue';
import { s__ } from '~/locale';
import { timeIntervalInWords } from '~/lib/utils/datetime_utility';
import tooltip from '~/vue_shared/directives/tooltip';
import icon from '~/vue_shared/components/icon.vue';
import { TIME_DIFF } from '../constants';
import { TIME_DIFF } from '../constants';
export default {
export default {
directives: {
tooltip,
},
......@@ -80,8 +80,7 @@
statusIcon(syncLag) {
if (syncLag <= TIME_DIFF.FIVE_MINS) {
return 'retry';
} else if (syncLag > TIME_DIFF.FIVE_MINS &&
syncLag <= TIME_DIFF.HOUR) {
} else if (syncLag > TIME_DIFF.FIVE_MINS && syncLag <= TIME_DIFF.HOUR) {
return 'warning';
}
return 'status_failed';
......@@ -92,17 +91,17 @@
return `${timeAgoStr} (${pendingEvents} events)`;
},
statusTooltip(lagInSeconds) {
if (this.eventTimestampEmpty ||
lagInSeconds <= TIME_DIFF.FIVE_MINS) {
if (this.eventTimestampEmpty || lagInSeconds <= TIME_DIFF.FIVE_MINS) {
return '';
} else if (lagInSeconds > TIME_DIFF.FIVE_MINS &&
lagInSeconds <= TIME_DIFF.HOUR) {
return s__('GeoNodeSyncStatus|Node is slow, overloaded, or it just recovered after an outage.');
} else if (lagInSeconds > TIME_DIFF.FIVE_MINS && lagInSeconds <= TIME_DIFF.HOUR) {
return s__(
'GeoNodeSyncStatus|Node is slow, overloaded, or it just recovered after an outage.',
);
}
return s__('GeoNodeSyncStatus|Node is failing or broken.');
},
},
};
};
</script>
<template>
......
<script>
import { __ } from '~/locale';
import { __ } from '~/locale';
import GeoNodeHealthStatus from '../geo_node_health_status.vue';
import GeoNodeActions from '../geo_node_actions.vue';
import GeoNodeHealthStatus from '../geo_node_health_status.vue';
import GeoNodeActions from '../geo_node_actions.vue';
export default {
export default {
components: {
GeoNodeHealthStatus,
GeoNodeActions,
......@@ -33,8 +33,7 @@
},
computed: {
nodeVersion() {
if (this.nodeDetails.version == null &&
this.nodeDetails.revision == null) {
if (this.nodeDetails.version == null && this.nodeDetails.revision == null) {
return __('Unknown');
}
return `${this.nodeDetails.version} (${this.nodeDetails.revision})`;
......@@ -43,7 +42,7 @@
return this.nodeDetails.healthy ? this.nodeDetails.health : this.nodeDetails.healthStatus;
},
},
};
};
</script>
<template>
......
<script>
import { s__, __ } from '~/locale';
import { numberToHumanSize } from '~/lib/utils/number_utils';
import { s__, __ } from '~/locale';
import { numberToHumanSize } from '~/lib/utils/number_utils';
import { VALUE_TYPE } from '../../constants';
import { VALUE_TYPE } from '../../constants';
import DetailsSectionMixin from '../../mixins/details_section_mixin';
import DetailsSectionMixin from '../../mixins/details_section_mixin';
import GeoNodeDetailItem from '../geo_node_detail_item.vue';
import SectionRevealButton from './section_reveal_button.vue';
import GeoNodeDetailItem from '../geo_node_detail_item.vue';
import SectionRevealButton from './section_reveal_button.vue';
export default {
export default {
valueType: VALUE_TYPE,
components: {
SectionRevealButton,
GeoNodeDetailItem,
},
mixins: [
DetailsSectionMixin,
],
mixins: [DetailsSectionMixin],
props: {
nodeDetails: {
type: Object,
......@@ -48,14 +46,12 @@
];
if (this.nodeDetails.replicationSlots.totalCount) {
primaryNodeDetailItems.push(
{
primaryNodeDetailItems.push({
itemTitle: s__('GeoNodes|Replication slot WAL'),
itemValue: numberToHumanSize(this.nodeDetails.replicationSlotWAL),
itemValueType: VALUE_TYPE.PLAIN,
cssClass: 'node-detail-value-bold',
},
);
});
}
return primaryNodeDetailItems;
......@@ -75,11 +71,15 @@
if (this.nodeDetails.storageShardsMatch == null) {
return __('Unknown');
}
return this.nodeDetails.storageShardsMatch ? __('OK') : s__('GeoNodes|Does not match the primary storage configuration');
return this.nodeDetails.storageShardsMatch
? __('OK')
: s__('GeoNodes|Does not match the primary storage configuration');
},
storageShardsCssClass() {
const cssClass = 'node-detail-value-bold';
return !this.nodeDetails.storageShardsMatch ? `${cssClass} node-detail-value-error` : cssClass;
return !this.nodeDetails.storageShardsMatch
? `${cssClass} node-detail-value-error`
: cssClass;
},
},
methods: {
......@@ -87,7 +87,7 @@
this.showSectionItems = toggleState;
},
},
};
};
</script>
<template>
......
<script>
import { s__ } from '~/locale';
import { s__ } from '~/locale';
import { VALUE_TYPE, HELP_INFO_URL } from '../../constants';
import { VALUE_TYPE, HELP_INFO_URL } from '../../constants';
import DetailsSectionMixin from '../../mixins/details_section_mixin';
import DetailsSectionMixin from '../../mixins/details_section_mixin';
import GeoNodeDetailItem from '../geo_node_detail_item.vue';
import SectionRevealButton from './section_reveal_button.vue';
import GeoNodeDetailItem from '../geo_node_detail_item.vue';
import SectionRevealButton from './section_reveal_button.vue';
export default {
export default {
components: {
GeoNodeDetailItem,
SectionRevealButton,
},
mixins: [
DetailsSectionMixin,
],
mixins: [DetailsSectionMixin],
props: {
nodeDetails: {
type: Object,
......@@ -35,9 +33,9 @@
},
computed: {
nodeDetailItems() {
return this.nodeTypePrimary ?
this.getPrimaryNodeDetailItems() :
this.getSecondaryNodeDetailItems();
return this.nodeTypePrimary
? this.getPrimaryNodeDetailItems()
: this.getSecondaryNodeDetailItems();
},
},
methods: {
......@@ -51,7 +49,9 @@
neutraLabel: s__('GeoNodes|Not checksummed'),
failureLabel: s__('GeoNodes|Failed'),
helpInfo: {
title: s__('GeoNodes|Repositories checksummed for verification with their counterparts on Secondary nodes'),
title: s__(
'GeoNodes|Repositories checksummed for verification with their counterparts on Secondary nodes',
),
url: HELP_INFO_URL,
urlText: s__('GeoNodes|Learn more about Repository checksum progress'),
},
......@@ -64,7 +64,9 @@
neutraLabel: s__('GeoNodes|Not checksummed'),
failureLabel: s__('GeoNodes|Failed'),
helpInfo: {
title: s__('GeoNodes|Wikis checksummed for verification with their counterparts on Secondary nodes'),
title: s__(
'GeoNodes|Wikis checksummed for verification with their counterparts on Secondary nodes',
),
url: HELP_INFO_URL,
urlText: s__('GeoNodes|Learn more about Wiki checksum progress'),
},
......@@ -81,7 +83,9 @@
neutraLabel: s__('GeoNodes|Unverified'),
failureLabel: s__('GeoNodes|Failed'),
helpInfo: {
title: s__('GeoNodes|Repositories verified with their counterparts on the Primary node'),
title: s__(
'GeoNodes|Repositories verified with their counterparts on the Primary node',
),
url: HELP_INFO_URL,
urlText: s__('GeoNodes|Learn more about Repository verification'),
},
......@@ -105,7 +109,7 @@
this.showSectionItems = toggleState;
},
},
};
};
</script>
<template>
......
<script>
import icon from '~/vue_shared/components/icon.vue';
import icon from '~/vue_shared/components/icon.vue';
export default {
export default {
components: {
icon,
},
......@@ -27,7 +27,7 @@
this.$emit('toggleButton', this.toggleState);
},
},
};
};
</script>
<template>
......
......@@ -30,4 +30,5 @@ export const TIME_DIFF = {
export const STATUS_DELAY_THRESHOLD_MS = 60000;
export const HELP_INFO_URL = 'https://docs.gitlab.com/ee/administration/geo/disaster_recovery/background_verification.html#repository-verification';
export const HELP_INFO_URL =
'https://docs.gitlab.com/ee/administration/geo/disaster_recovery/background_verification.html#repository-verification';
......@@ -13,9 +13,7 @@ export default {
},
statusInfoStaleMessage() {
return sprintf(s__('GeoNodes|Data is out of date from %{timeago}'), {
timeago: this.timeFormated(
this.nodeDetails.statusCheckTimestamp,
),
timeago: this.timeFormated(this.nodeDetails.statusCheckTimestamp),
});
},
},
......
......@@ -8,9 +8,7 @@ export default class GeoNodesStore {
}
setNodes(nodes) {
this.state.nodes = nodes.map(
node => GeoNodesStore.formatNode(node),
);
this.state.nodes = nodes.map(node => GeoNodesStore.formatNode(node));
}
getNodes() {
......
......@@ -19,7 +19,7 @@ const setupAutoCompleteEpics = ($input, defaultCallbacks) => {
callbacks: {
...defaultCallbacks,
beforeSave(merges) {
return $.map(merges, (m) => {
return $.map(merges, m => {
if (m.title == null) {
return m;
}
......
......@@ -11,18 +11,16 @@ export default () => {
modal: true,
show: false,
})
.on('show.bs.modal', (e) => {
const {
cloneUrlPrimary,
cloneUrlSecondary,
} = $(e.currentTarget).data();
.on('show.bs.modal', e => {
const { cloneUrlPrimary, cloneUrlSecondary } = $(e.currentTarget).data();
$('#geo-info-1').val(
`git clone ${(cloneUrlSecondary || '<clone url for secondary repository>')}`,
`git clone ${cloneUrlSecondary || '<clone url for secondary repository>'}`,
);
$('#geo-info-2').val(
`git remote set-url --push origin ${(cloneUrlPrimary || '<clone url for primary repository>')}`,
`git remote set-url --push origin ${cloneUrlPrimary ||
'<clone url for primary repository>'}`,
);
});
};
......@@ -78,11 +78,15 @@ export default class KubernetesPodLogs extends LogOutputBehaviours {
this.$podDropdown
.find('.dropdown-menu-toggle')
.html(`<span class="dropdown-toggle-text">${this.podName}</span><i class="fa fa-chevron-down"></i>`);
.html(
`<span class="dropdown-toggle-text">${
this.podName
}</span><i class="fa fa-chevron-down"></i>`,
);
$podDropdownMenu.off('click');
$podDropdownMenu.empty();
pods.forEach((pod) => {
pods.forEach(pod => {
$podDropdownMenu.append(`
<button class='dropdown-item'>
${_.escape(pod)}
......
......@@ -16,7 +16,7 @@ export default function initLDAPGroupsSelect() {
id: function(group) {
return group.cn;
},
placeholder: "Search for a LDAP group",
placeholder: 'Search for a LDAP group',
minimumInputLength: 1,
query: function(query) {
var provider;
......@@ -24,7 +24,7 @@ export default function initLDAPGroupsSelect() {
return Api.ldap_groups(query.term, provider, function(groups) {
var data;
data = {
results: groups
results: groups,
};
return query.callback(data);
});
......@@ -32,18 +32,18 @@ export default function initLDAPGroupsSelect() {
initSelection: function(element, callback) {
var id;
id = $(element).val();
if (id !== "") {
if (id !== '') {
return callback({
cn: id
cn: id,
});
}
},
formatResult: ldapGroupResult,
formatSelection: groupFormatSelection,
dropdownCssClass: "ajax-groups-dropdown",
dropdownCssClass: 'ajax-groups-dropdown',
formatNoMatches: function(nomatch) {
return "Match not found; try refining your search query.";
}
return 'Match not found; try refining your search query.';
},
});
});
return $('#ldap_group_link_provider').on('change', function() {
......
......@@ -96,7 +96,11 @@ export default class MirrorPull {
// Make backOff polling to get data
backOff((next, stop) => {
axios
.get(`${projectMirrorSSHEndpoint}?ssh_url=${repositoryUrl}&compare_host_keys=${encodeURIComponent(currentKnownHosts)}`)
.get(
`${projectMirrorSSHEndpoint}?ssh_url=${repositoryUrl}&compare_host_keys=${encodeURIComponent(
currentKnownHosts,
)}`,
)
.then(({ data, status }) => {
if (status === 204) {
this.backOffRequestCounter += 1;
......
......@@ -97,9 +97,7 @@ export default {
this.isLoading = true;
return Promise.all(
this.alerts.map(alertPath =>
this.service
.readAlert(alertPath)
.then(alertData => {
this.service.readAlert(alertPath).then(alertData => {
this.$emit('setAlerts', this.customMetricId, {
...this.alertData,
[alertPath]: alertData,
......
......@@ -26,17 +26,15 @@ export default {
const [xMin, xMax] = this.graphDrawData.xDom;
const [yMin, yMax] = this.graphDrawData.yDom;
const outOfRange = (this.operator === '>' && this.threshold > yMax) ||
const outOfRange =
(this.operator === '>' && this.threshold > yMax) ||
(this.operator === '<' && this.threshold < yMin);
if (outOfRange) {
return [];
}
return [
{ time: xMin, value: this.threshold },
{ time: xMax, value: this.threshold },
];
return [{ time: xMin, value: this.threshold }, { time: xMax, value: this.threshold }];
},
linePath() {
if (!this.graphDrawData.lineFunction) {
......
......@@ -4,38 +4,39 @@ import $ from 'jquery';
import Api from '~/api';
function AdminEmailSelect() {
$('.ajax-admin-email-select').each((function(_this) {
$('.ajax-admin-email-select').each(
(function(_this) {
return function(i, select) {
var skip_ldap;
skip_ldap = $(select).hasClass('skip_ldap');
return $(select).select2({
placeholder: "Select group or project",
placeholder: 'Select group or project',
multiple: $(select).hasClass('multiselect'),
minimumInputLength: 0,
query: function(query) {
const groupsFetch = Api.groups(query.term, {});
const projectsFetch = Api.projects(query.term, {
order_by: 'id',
membership: false
membership: false,
});
return Promise.all([projectsFetch, groupsFetch]).then(function([projects, groups]) {
var all, data;
all = {
id: "all"
id: 'all',
};
data = [all].concat(groups, projects);
return query.callback({
results: data
results: data,
});
});
},
id: function(object) {
if (object.path_with_namespace) {
return "project-" + object.id;
return 'project-' + object.id;
} else if (object.path) {
return "group-" + object.id;
return 'group-' + object.id;
} else {
return "all";
return 'all';
}
},
formatResult(...args) {
......@@ -44,20 +45,33 @@ function AdminEmailSelect() {
formatSelection(...args) {
return _this.formatSelection(...args);
},
dropdownCssClass: "ajax-admin-email-dropdown",
dropdownCssClass: 'ajax-admin-email-dropdown',
escapeMarkup: function(m) {
return m;
}
},
});
};
})(this));
})(this),
);
}
AdminEmailSelect.prototype.formatResult = function(object) {
if (object.path_with_namespace) {
return "<div class='project-result'> <div class='project-name'>" + object.name + "</div> <div class='project-path'>" + object.path_with_namespace + "</div> </div>";
return (
"<div class='project-result'> <div class='project-name'>" +
object.name +
"</div> <div class='project-path'>" +
object.path_with_namespace +
'</div> </div>'
);
} else if (object.path) {
return "<div class='group-result'> <div class='group-name'>" + object.name + "</div> <div class='group-path'>" + object.path + "</div> </div>";
return (
"<div class='group-result'> <div class='group-name'>" +
object.name +
"</div> <div class='group-path'>" +
object.path +
'</div> </div>'
);
} else {
return "<div class='group-result'> <div class='group-name'>All</div> <div class='group-path'>All groups and projects</div> </div>";
}
......@@ -65,11 +79,11 @@ AdminEmailSelect.prototype.formatResult = function(object) {
AdminEmailSelect.prototype.formatSelection = function(object) {
if (object.path_with_namespace) {
return "Project: " + object.name;
return 'Project: ' + object.name;
} else if (object.path) {
return "Group: " + object.name;
return 'Group: ' + object.name;
} else {
return "All groups and projects";
return 'All groups and projects';
}
};
......
......@@ -24,11 +24,11 @@ export default function geoNodeForm() {
const $syncByNamespaces = $('.js-sync-by-namespace', $container);
const $syncByShards = $('.js-sync-by-shard', $container);
$primaryCheckbox.on('change', e =>
onPrimaryCheckboxChange(e, $namespaces));
$primaryCheckbox.on('change', e => onPrimaryCheckboxChange(e, $namespaces));
$selectiveSyncTypeSelect.on('change', e =>
onSelectiveSyncTypeChange(e, $syncByNamespaces, $syncByShards));
onSelectiveSyncTypeChange(e, $syncByNamespaces, $syncByShards),
);
$select2Dropdown.select2({
placeholder: s__('Geo|Select groups to replicate.'),
......
......@@ -25,7 +25,7 @@ document.addEventListener('DOMContentLoaded', () => {
merge_requests_created: [],
};
outputElIds.forEach((id) => {
outputElIds.forEach(id => {
data[id].data.forEach((d, index) => {
formattedData[id].push({
name: data.labels[index],
......
......@@ -107,8 +107,7 @@ export default class EEMirrorRepos extends MirrorRepos {
};
}
return super.deleteMirror(event, payload)
.then(() => {
return super.deleteMirror(event, payload).then(() => {
if (isPullMirror) this.$mirrorDirectionSelect.removeAttr('disabled');
});
}
......
......@@ -4,10 +4,7 @@ export default () => {
const dataEl = document.getElementById('js-file-lock');
if (dataEl) {
const {
toggle_path,
path,
} = JSON.parse(dataEl.innerHTML);
const { toggle_path, path } = JSON.parse(dataEl.innerHTML);
initPathLocks(toggle_path, path);
}
......
......@@ -4,13 +4,16 @@ import { __ } from '~/locale';
import axios from '~/lib/utils/axios_utils';
export default function initPathLocks(url, path) {
$('a.path-lock').on('click', (e) => {
$('a.path-lock').on('click', e => {
e.preventDefault();
axios.post(url, {
axios
.post(url, {
path,
}).then(() => {
})
.then(() => {
window.location.reload();
}).catch(() => flash(__('An error occurred while initializing path locks')));
})
.catch(() => flash(__('An error occurred while initializing path locks')));
});
}
<script>
import ciStatus from '~/vue_shared/components/ci_icon.vue';
import tooltip from '~/vue_shared/directives/tooltip';
import ciStatus from '~/vue_shared/components/ci_icon.vue';
import tooltip from '~/vue_shared/directives/tooltip';
export default {
export default {
directives: {
tooltip,
},
......@@ -32,7 +32,7 @@
return `${this.projectName} - ${this.pipelineStatus.label}`;
},
},
};
};
</script>
<template>
......
<script>
import linkedPipeline from './linked_pipeline.vue';
import linkedPipeline from './linked_pipeline.vue';
export default {
export default {
components: {
linkedPipeline,
},
......@@ -25,7 +25,7 @@
return `graph-position-${this.graphPosition}`;
},
},
};
};
</script>
<template>
......
......@@ -46,8 +46,9 @@ const bindEvents = () => {
const $activeTabProjectName = $('.tab-pane.active #project_name');
const $activeTabProjectPath = $('.tab-pane.active #project_path');
$activeTabProjectName.focus();
$activeTabProjectName
.keyup(() => projectNew.onProjectNameChange($activeTabProjectName, $activeTabProjectPath));
$activeTabProjectName.keyup(() =>
projectNew.onProjectNameChange($activeTabProjectName, $activeTabProjectPath),
);
}
$useCustomTemplateBtn.on('change', chooseTemplate);
......@@ -60,7 +61,6 @@ const bindEvents = () => {
};
export default () => {
const $navElement = $('.nav-link[href="#custom-templates"]');
const $tabContent = $('.project-templates-buttons#custom-templates');
......
<script>
import Flash from '~/flash';
import serviceDeskSetting from './service_desk_setting.vue';
import ServiceDeskStore from '../stores/service_desk_store';
import ServiceDeskService from '../services/service_desk_service';
import eventHub from '../event_hub';
import Flash from '~/flash';
import serviceDeskSetting from './service_desk_setting.vue';
import ServiceDeskStore from '../stores/service_desk_store';
import ServiceDeskService from '../services/service_desk_service';
import eventHub from '../event_hub';
export default {
export default {
name: 'ServiceDeskRoot',
components: {
......@@ -59,18 +59,23 @@
this.flash.innerHTML = '';
}
this.service.fetchIncomingEmail()
this.service
.fetchIncomingEmail()
.then(res => res.json())
.then((data) => {
.then(data => {
const email = data.service_desk_address;
if (!email) {
throw new Error('Response didn\'t include `service_desk_address`');
throw new Error("Response didn't include `service_desk_address`");
}
this.store.setIncomingEmail(email);
})
.catch(() => {
this.flash = new Flash('An error occurred while fetching the Service Desk address.', 'alert', this.$el);
this.flash = new Flash(
'An error occurred while fetching the Service Desk address.',
'alert',
this.$el,
);
});
},
......@@ -81,23 +86,28 @@
this.flash.destroy();
}
this.service.toggleServiceDesk(isChecked)
this.service
.toggleServiceDesk(isChecked)
.then(res => res.json())
.then((data) => {
.then(data => {
const email = data.service_desk_address;
if (isChecked && !email) {
throw new Error('Response didn\'t include `service_desk_address`');
throw new Error("Response didn't include `service_desk_address`");
}
this.store.setIncomingEmail(email);
})
.catch(() => {
const verb = isChecked ? 'enabling' : 'disabling';
this.flash = new Flash(`An error occurred while ${verb} Service Desk.`, 'alert', this.$el);
this.flash = new Flash(
`An error occurred while ${verb} Service Desk.`,
'alert',
this.$el,
);
});
},
},
};
};
</script>
<template>
......
<script>
import tooltip from '~/vue_shared/directives/tooltip';
import ClipboardButton from '~/vue_shared/components/clipboard_button.vue';
import eventHub from '../event_hub';
import tooltip from '~/vue_shared/directives/tooltip';
import ClipboardButton from '~/vue_shared/components/clipboard_button.vue';
import eventHub from '../event_hub';
export default {
export default {
name: 'ServiceDeskSetting',
directives: {
tooltip,
......@@ -30,7 +30,7 @@
eventHub.$emit('serviceDeskEnabledCheckboxToggled', isChecked);
},
},
};
};
</script>
<template>
......
......@@ -14,9 +14,7 @@ export default () => {
data() {
const { dataset } = serviceDeskRootElement;
return {
initialIsEnabled: convertPermissionToBoolean(
dataset.enabled,
),
initialIsEnabled: convertPermissionToBoolean(dataset.enabled),
endpoint: dataset.endpoint,
incomingEmail: dataset.incomingEmail,
};
......
class ServiceDeskStore {
constructor(initialState = {}) {
this.state = Object.assign({
this.state = Object.assign(
{
incomingEmail: '',
}, initialState);
},
initialState,
);
}
setIncomingEmail(value) {
......
import Stats from 'ee/stats';
const bindTrackEvents = (container) => {
const bindTrackEvents = container => {
Stats.bindTrackableContainer(container);
};
......
......@@ -11,18 +11,32 @@ export default class EEPrometheusMetrics extends PrometheusMetrics {
super(wrapperSelector);
this.$wrapperCustomMetrics = $(wrapperSelector);
this.$monitoredCustomMetricsPanel = this.$wrapperCustomMetrics.find('.js-panel-custom-monitored-metrics');
this.$monitoredCustomMetricsCount = this.$monitoredCustomMetricsPanel.find('.js-custom-monitored-count');
this.$monitoredCustomMetricsLoading = this.$monitoredCustomMetricsPanel.find('.js-loading-custom-metrics');
this.$monitoredCustomMetricsEmpty = this.$monitoredCustomMetricsPanel.find('.js-empty-custom-metrics');
this.$monitoredCustomMetricsList = this.$monitoredCustomMetricsPanel.find('.js-custom-metrics-list');
this.$monitoredCustomMetricsPanel = this.$wrapperCustomMetrics.find(
'.js-panel-custom-monitored-metrics',
);
this.$monitoredCustomMetricsCount = this.$monitoredCustomMetricsPanel.find(
'.js-custom-monitored-count',
);
this.$monitoredCustomMetricsLoading = this.$monitoredCustomMetricsPanel.find(
'.js-loading-custom-metrics',
);
this.$monitoredCustomMetricsEmpty = this.$monitoredCustomMetricsPanel.find(
'.js-empty-custom-metrics',
);
this.$monitoredCustomMetricsList = this.$monitoredCustomMetricsPanel.find(
'.js-custom-metrics-list',
);
this.$newCustomMetricButton = this.$monitoredCustomMetricsPanel.find('.js-new-metric-button');
this.$flashCustomMetricsContainer = this.$wrapperCustomMetrics.find('.flash-container');
this.customMetrics = [];
this.environmentsData = [];
this.activeCustomMetricsEndpoint = this.$monitoredCustomMetricsPanel.data('active-custom-metrics');
this.environmentsDataEndpoint = this.$monitoredCustomMetricsPanel.data('environments-data-endpoint');
this.activeCustomMetricsEndpoint = this.$monitoredCustomMetricsPanel.data(
'active-custom-metrics',
);
this.environmentsDataEndpoint = this.$monitoredCustomMetricsPanel.data(
'environments-data-endpoint',
);
}
showMonitoringCustomMetricsPanelState(stateName) {
......@@ -49,20 +63,25 @@ export default class EEPrometheusMetrics extends PrometheusMetrics {
}
populateCustomMetrics() {
const sortedMetrics = _(this.customMetrics).chain()
const sortedMetrics = _(this.customMetrics)
.chain()
.map(metric => ({ ...metric, group: capitalizeFirstCharacter(metric.group) }))
.sortBy('title')
.sortBy('group')
.value();
sortedMetrics.forEach((metric) => {
sortedMetrics.forEach(metric => {
this.$monitoredCustomMetricsList.append(EEPrometheusMetrics.customMetricTemplate(metric));
});
this.$monitoredCustomMetricsCount.text(this.customMetrics.length);
this.showMonitoringCustomMetricsPanelState(PANEL_STATE.LIST);
if (!this.environmentsData) {
this.showFlashMessage(s__('PrometheusService|These metrics will only be monitored after your first deployment to an environment'));
this.showFlashMessage(
s__(
'PrometheusService|These metrics will only be monitored after your first deployment to an environment',
),
);
}
}
......@@ -86,7 +105,7 @@ export default class EEPrometheusMetrics extends PrometheusMetrics {
this.populateCustomMetrics(customMetrics.data.metrics);
}
})
.catch((customMetricError) => {
.catch(customMetricError => {
this.showFlashMessage(customMetricError);
this.showMonitoringCustomMetricsPanelState(PANEL_STATE.EMPTY);
});
......
......@@ -17,4 +17,3 @@ export default class ProtectedEnvironmentEditList {
});
}
}
......@@ -43,8 +43,9 @@ export default {
return `Paste issue link${this.allowAutoComplete ? ' or <#issue id>' : ''}`;
},
isSubmitButtonDisabled() {
return (this.inputValue.length === 0 && this.pendingReferences.length === 0)
|| this.isSubmitting;
return (
(this.inputValue.length === 0 && this.pendingReferences.length === 0) || this.isSubmitting
);
},
allowAutoComplete() {
return Object.keys(this.autoCompleteSources).length > 0;
......
......@@ -113,10 +113,10 @@ export default {
if (issueToRemove) {
RelatedIssuesService.remove(issueToRemove.relation_path)
.then(res => res.json())
.then((data) => {
.then(data => {
this.store.setRelatedIssues(data.issues);
})
.catch((res) => {
.catch(res => {
if (res && res.status !== 404) {
Flash('An error occurred while removing issues.');
}
......@@ -136,9 +136,10 @@ export default {
if (this.state.pendingReferences.length > 0) {
this.isSubmitting = true;
this.service.addRelatedIssues(this.state.pendingReferences)
this.service
.addRelatedIssues(this.state.pendingReferences)
.then(res => res.json())
.then((data) => {
.then(data => {
// We could potentially lose some pending issues in the interim here
this.store.setPendingReferences([]);
this.store.setRelatedIssues(data.issues);
......@@ -147,9 +148,9 @@ export default {
// Close the form on submission
this.isFormVisible = false;
})
.catch((res) => {
.catch(res => {
this.isSubmitting = false;
let errorMessage = 'We can\'t find an issue that matches what you are looking for.';
let errorMessage = "We can't find an issue that matches what you are looking for.";
if (res.data && res.data.message) {
errorMessage = res.data.message;
}
......@@ -164,9 +165,10 @@ export default {
},
fetchRelatedIssues() {
this.isFetching = true;
this.service.fetchRelatedIssues()
this.service
.fetchRelatedIssues()
.then(res => res.json())
.then((issues) => {
.then(issues => {
this.store.setRelatedIssues(issues);
this.isFetching = false;
})
......@@ -186,7 +188,7 @@ export default {
move_after_id: afterId,
})
.then(res => res.json())
.then((res) => {
.then(res => {
if (!res.message) {
this.store.updateIssueOrder(oldIndex, newIndex);
}
......@@ -197,15 +199,14 @@ export default {
}
},
onInput(newValue, caretPos) {
const rawReferences = newValue
.split(/\s/);
const rawReferences = newValue.split(/\s/);
let touchedReference;
let iteratingPos = 0;
const untouchedRawReferences = rawReferences
.filter((reference) => {
.filter(reference => {
let isTouched = false;
if (caretPos >= iteratingPos && caretPos <= (iteratingPos + reference.length)) {
if (caretPos >= iteratingPos && caretPos <= iteratingPos + reference.length) {
touchedReference = reference;
isTouched = true;
}
......@@ -216,22 +217,16 @@ export default {
})
.filter(reference => reference.trim().length > 0);
this.store.setPendingReferences(
this.state.pendingReferences.concat(untouchedRawReferences),
);
this.store.setPendingReferences(this.state.pendingReferences.concat(untouchedRawReferences));
this.inputValue = `${touchedReference}`;
},
onBlur(newValue) {
this.processAllReferences(newValue);
},
processAllReferences(value = '') {
const rawReferences = value
.split(/\s+/)
.filter(reference => reference.trim().length > 0);
const rawReferences = value.split(/\s+/).filter(reference => reference.trim().length > 0);
this.store.setPendingReferences(
this.state.pendingReferences.concat(rawReferences),
);
this.store.setPendingReferences(this.state.pendingReferences.concat(rawReferences));
this.inputValue = '';
},
},
......
......@@ -11,7 +11,8 @@ export default function initRelatedIssues() {
components: {
relatedIssuesRoot: RelatedIssuesRoot,
},
render: createElement => createElement('related-issues-root', {
render: createElement =>
createElement('related-issues-root', {
props: {
endpoint: relatedIssuesRootElement.dataset.endpoint,
canAdmin: convertPermissionToBoolean(
......
......@@ -13,9 +13,12 @@ class RelatedIssuesService {
}
addRelatedIssues(newIssueReferences) {
return this.relatedIssuesResource.save({}, {
return this.relatedIssuesResource.save(
{},
{
issue_references: newIssueReferences,
});
},
);
}
static saveOrder({ endpoint, move_before_id, move_after_id }) {
......
......@@ -28,10 +28,10 @@ class RelatedIssuesStore {
}
removePendingRelatedIssue(indexToRemove) {
this.state.pendingReferences =
this.state.pendingReferences.filter((reference, index) => index !== indexToRemove);
this.state.pendingReferences = this.state.pendingReferences.filter(
(reference, index) => index !== indexToRemove,
);
}
}
export default RelatedIssuesStore;
<script>
import _ from 'underscore';
import Flash from '~/flash';
import { s__ } from '~/locale';
import _ from 'underscore';
import Flash from '~/flash';
import { s__ } from '~/locale';
import epicsListEmpty from './epics_list_empty.vue';
import roadmapShell from './roadmap_shell.vue';
import epicsListEmpty from './epics_list_empty.vue';
import roadmapShell from './roadmap_shell.vue';
export default {
export default {
components: {
epicsListEmpty,
roadmapShell,
......@@ -77,9 +77,10 @@
methods: {
fetchEpics() {
this.hasError = false;
this.service.getEpics()
this.service
.getEpics()
.then(res => res.data)
.then((epics) => {
.then(epics => {
this.isLoading = false;
if (epics.length) {
this.store.setEpics(epics);
......@@ -115,7 +116,7 @@
}, 200)();
},
},
};
};
</script>
<template>
......
<script>
import epicItemDetails from './epic_item_details.vue';
import epicItemTimeline from './epic_item_timeline.vue';
import epicItemDetails from './epic_item_details.vue';
import epicItemTimeline from './epic_item_timeline.vue';
export default {
export default {
components: {
epicItemDetails,
epicItemTimeline,
......@@ -33,7 +33,7 @@
required: true,
},
},
};
};
</script>
<template>
......
<script>
import { s__, sprintf } from '~/locale';
import { dateInWords } from '~/lib/utils/datetime_utility';
import tooltip from '~/vue_shared/directives/tooltip';
import { s__, sprintf } from '~/locale';
import { dateInWords } from '~/lib/utils/datetime_utility';
import tooltip from '~/vue_shared/directives/tooltip';
export default {
export default {
directives: {
tooltip,
},
......@@ -68,7 +68,7 @@
return `${startDateInWords} &ndash; ${dateInWords(this.endDate, true)}`;
},
},
};
};
</script>
<template>
......
......@@ -17,11 +17,7 @@ export default {
directives: {
tooltip,
},
mixins: [
QuartersPresetMixin,
MonthsPresetMixin,
WeeksPresetMixin,
],
mixins: [QuartersPresetMixin, MonthsPresetMixin, WeeksPresetMixin],
props: {
presetType: {
type: String,
......
<script>
import eventHub from '../event_hub';
import eventHub from '../event_hub';
import SectionMixin from '../mixins/section_mixin';
import SectionMixin from '../mixins/section_mixin';
import epicItem from './epic_item.vue';
import epicItem from './epic_item.vue';
export default {
export default {
components: {
epicItem,
},
mixins: [
SectionMixin,
],
mixins: [SectionMixin],
props: {
presetType: {
type: String,
......@@ -114,14 +112,14 @@
if (approxChildrenHeight < this.shellHeight) {
// reset approximate height and recalculate actual height
approxChildrenHeight = 0;
children.forEach((child) => {
children.forEach(child => {
// accumulate children height
// compensate for bottom border
approxChildrenHeight += child.$el.clientHeight;
});
// set height and show empty row reducing horizontal scrollbar size
this.emptyRowHeight = (this.shellHeight - approxChildrenHeight);
this.emptyRowHeight = this.shellHeight - approxChildrenHeight;
this.showEmptyRow = true;
} else {
this.showBottomShadow = true;
......@@ -138,10 +136,10 @@
this.$el.scrollTo(uptoTodayIndicator, 0);
},
handleEpicsListScroll({ scrollTop, clientHeight, scrollHeight }) {
this.showBottomShadow = (Math.ceil(scrollTop) + clientHeight) < scrollHeight;
this.showBottomShadow = Math.ceil(scrollTop) + clientHeight < scrollHeight;
},
},
};
};
</script>
<template>
......
<script>
import { monthInWords } from '~/lib/utils/datetime_utility';
import { monthInWords } from '~/lib/utils/datetime_utility';
import MonthsHeaderSubItem from './months_header_sub_item.vue';
import MonthsHeaderSubItem from './months_header_sub_item.vue';
export default {
export default {
components: {
MonthsHeaderSubItem,
},
......@@ -51,8 +51,10 @@
//
// End result of doing this is;
// 2017 Nov, Dec, 2018 Jan, Feb, Mar
if (this.timeframeIndex !== 0 &&
this.timeframe[this.timeframeIndex - 1].getFullYear() === year) {
if (
this.timeframeIndex !== 0 &&
this.timeframe[this.timeframeIndex - 1].getFullYear() === year
) {
return month;
}
......@@ -66,22 +68,20 @@
// Show dark color text only if timeframe item year & month
// are greater than current year.
if (timeframeYear >= this.currentYear &&
timeframeMonth >= this.currentMonth) {
if (timeframeYear >= this.currentYear && timeframeMonth >= this.currentMonth) {
itemLabelClass += 'label-dark';
}
// Show bold text only if timeframe item year & month
// is current year & month
if (timeframeYear === this.currentYear &&
timeframeMonth === this.currentMonth) {
if (timeframeYear === this.currentYear && timeframeMonth === this.currentMonth) {
itemLabelClass += ' label-bold';
}
return itemLabelClass;
},
},
};
};
</script>
<template>
......
<script>
import { getSundays } from '~/lib/utils/datetime_utility';
import { getSundays } from '~/lib/utils/datetime_utility';
import { PRESET_TYPES } from '../../constants';
import { PRESET_TYPES } from '../../constants';
import timelineTodayIndicator from '../timeline_today_indicator.vue';
import timelineTodayIndicator from '../timeline_today_indicator.vue';
export default {
export default {
presetType: PRESET_TYPES.MONTHS,
components: {
timelineTodayIndicator,
......@@ -37,8 +37,10 @@
const timeframeYear = this.timeframeItem.getFullYear();
const timeframeMonth = this.timeframeItem.getMonth();
return this.currentDate.getMonth() === timeframeMonth &&
this.currentDate.getFullYear() === timeframeYear;
return (
this.currentDate.getMonth() === timeframeMonth &&
this.currentDate.getFullYear() === timeframeYear
);
},
},
methods: {
......@@ -46,10 +48,12 @@
const daysToClosestWeek = this.currentDate.getDate() - subItem.getDate();
// Show dark color text only for upcoming dates
// and current week date
if (daysToClosestWeek <= 6 &&
if (
daysToClosestWeek <= 6 &&
this.currentDate.getDate() >= subItem.getDate() &&
this.currentDate.getFullYear() === subItem.getFullYear() &&
this.currentDate.getMonth() === subItem.getMonth()) {
this.currentDate.getMonth() === subItem.getMonth()
) {
return 'label-dark label-bold';
} else if (subItem >= this.currentDate) {
return 'label-dark';
......@@ -57,7 +61,7 @@
return '';
},
},
};
};
</script>
<template>
......
<script>
import QuartersHeaderSubItem from './quarters_header_sub_item.vue';
import QuartersHeaderSubItem from './quarters_header_sub_item.vue';
export default {
export default {
components: {
QuartersHeaderSubItem,
},
......@@ -41,8 +41,7 @@
},
timelineHeaderLabel() {
const { quarterSequence } = this.timeframeItem;
if (quarterSequence === 1 ||
this.timeframeIndex === 0 && quarterSequence !== 1) {
if (quarterSequence === 1 || (this.timeframeIndex === 0 && quarterSequence !== 1)) {
return `${this.timeframeItem.year} Q${quarterSequence}`;
}
......@@ -50,8 +49,7 @@
},
timelineHeaderClass() {
let headerClass = '';
if (this.currentDate >= this.quarterBeginDate &&
this.currentDate <= this.quarterEndDate) {
if (this.currentDate >= this.quarterBeginDate && this.currentDate <= this.quarterEndDate) {
headerClass = 'label-dark label-bold';
} else if (this.currentDate < this.quarterBeginDate) {
headerClass = 'label-dark';
......@@ -60,7 +58,7 @@
return headerClass;
},
},
};
};
</script>
<template>
......
<script>
import { monthInWords } from '~/lib/utils/datetime_utility';
import { monthInWords } from '~/lib/utils/datetime_utility';
import { PRESET_TYPES } from '../../constants';
import { PRESET_TYPES } from '../../constants';
import timelineTodayIndicator from '../timeline_today_indicator.vue';
import timelineTodayIndicator from '../timeline_today_indicator.vue';
export default {
export default {
presetType: PRESET_TYPES.QUARTERS,
components: {
timelineTodayIndicator,
......@@ -31,16 +31,17 @@
return this.timeframeItem.range;
},
hasToday() {
return this.currentDate >= this.quarterBeginDate &&
this.currentDate <= this.quarterEndDate;
return this.currentDate >= this.quarterBeginDate && this.currentDate <= this.quarterEndDate;
},
},
methods: {
getSubItemValueClass(subItem) {
let itemValueClass = '';
if (this.currentDate.getFullYear() === subItem.getFullYear() &&
this.currentDate.getMonth() === subItem.getMonth()) {
if (
this.currentDate.getFullYear() === subItem.getFullYear() &&
this.currentDate.getMonth() === subItem.getMonth()
) {
itemValueClass = 'label-dark label-bold';
} else if (this.currentDate < subItem) {
itemValueClass = 'label-dark';
......@@ -51,7 +52,7 @@
return monthInWords(subItem, true);
},
},
};
};
</script>
<template>
......
<script>
import { monthInWords } from '~/lib/utils/datetime_utility';
import { monthInWords } from '~/lib/utils/datetime_utility';
import WeeksHeaderSubItem from './weeks_header_sub_item.vue';
import WeeksHeaderSubItem from './weeks_header_sub_item.vue';
export default {
export default {
components: {
WeeksHeaderSubItem,
},
......@@ -45,13 +45,15 @@
},
timelineHeaderLabel() {
if (this.timeframeIndex === 0) {
return `${this.timeframeItem.getFullYear()} ${monthInWords(this.timeframeItem, true)} ${this.timeframeItem.getDate()}`;
return `${this.timeframeItem.getFullYear()} ${monthInWords(
this.timeframeItem,
true,
)} ${this.timeframeItem.getDate()}`;
}
return `${monthInWords(this.timeframeItem, true)} ${this.timeframeItem.getDate()}`;
},
timelineHeaderClass() {
if (this.currentDate >= this.timeframeItem &&
this.currentDate <= this.lastDayOfCurrentWeek) {
if (this.currentDate >= this.timeframeItem && this.currentDate <= this.lastDayOfCurrentWeek) {
return 'label-dark label-bold';
} else if (this.currentDate < this.lastDayOfCurrentWeek) {
return 'label-dark';
......@@ -59,7 +61,7 @@
return '';
},
},
};
};
</script>
<template>
......
......@@ -23,7 +23,8 @@ export default {
const headerSubItems = new Array(7)
.fill()
.map(
(val, i) => new Date(
(val, i) =>
new Date(
timeframeItem.getFullYear(),
timeframeItem.getMonth(),
timeframeItem.getDate() + i,
......
<script>
import bp from '~/breakpoints';
import { SCROLL_BAR_SIZE, EPIC_ITEM_HEIGHT, SHELL_MIN_WIDTH } from '../constants';
import eventHub from '../event_hub';
import bp from '~/breakpoints';
import { SCROLL_BAR_SIZE, EPIC_ITEM_HEIGHT, SHELL_MIN_WIDTH } from '../constants';
import eventHub from '../event_hub';
import epicsListSection from './epics_list_section.vue';
import roadmapTimelineSection from './roadmap_timeline_section.vue';
import epicsListSection from './epics_list_section.vue';
import roadmapTimelineSection from './roadmap_timeline_section.vue';
export default {
export default {
components: {
epicsListSection,
roadmapTimelineSection,
......@@ -38,9 +38,10 @@
},
computed: {
containerStyles() {
const width = bp.windowWidth() > SHELL_MIN_WIDTH ?
this.shellWidth + this.getWidthOffset() :
this.shellWidth;
const width =
bp.windowWidth() > SHELL_MIN_WIDTH
? this.shellWidth + this.getWidthOffset()
: this.shellWidth;
return {
width: `${width}px`,
......@@ -58,7 +59,7 @@
// see https://vuejs.org/v2/api/#Vue-nextTick
if (this.$el.parentElement) {
this.shellHeight = window.innerHeight - this.$el.offsetTop;
this.noScroll = this.shellHeight > (EPIC_ITEM_HEIGHT * (this.epics.length + 1));
this.noScroll = this.shellHeight > EPIC_ITEM_HEIGHT * (this.epics.length + 1);
this.shellWidth = this.$el.parentElement.clientWidth + this.getWidthOffset();
}
});
......@@ -72,7 +73,7 @@
eventHub.$emit('epicsListScrolled', { scrollTop, scrollLeft, clientHeight, scrollHeight });
},
},
};
};
</script>
<template>
......
<script>
import eventHub from '../event_hub';
import eventHub from '../event_hub';
import { PRESET_TYPES } from '../constants';
import { PRESET_TYPES } from '../constants';
import SectionMixin from '../mixins/section_mixin';
import SectionMixin from '../mixins/section_mixin';
import QuartersHeaderItem from './preset_quarters/quarters_header_item.vue';
import MonthsHeaderItem from './preset_months/months_header_item.vue';
import WeeksHeaderItem from './preset_weeks/weeks_header_item.vue';
import QuartersHeaderItem from './preset_quarters/quarters_header_item.vue';
import MonthsHeaderItem from './preset_months/months_header_item.vue';
import WeeksHeaderItem from './preset_weeks/weeks_header_item.vue';
export default {
export default {
components: {
QuartersHeaderItem,
MonthsHeaderItem,
WeeksHeaderItem,
},
mixins: [
SectionMixin,
],
mixins: [SectionMixin],
props: {
presetType: {
type: String,
......@@ -66,10 +64,10 @@
methods: {
handleEpicsListScroll({ scrollTop }) {
// Add class only when epics list is scrolled at 1% the height of header
this.scrolledHeaderClass = (scrollTop > this.$el.clientHeight / 100) ? 'scroll-top-shadow' : '';
this.scrolledHeaderClass = scrollTop > this.$el.clientHeight / 100 ? 'scroll-top-shadow' : '';
},
},
};
};
</script>
<template>
......
......@@ -48,14 +48,16 @@ export default {
// based on the current presetType
if (this.presetType === PRESET_TYPES.QUARTERS) {
left = Math.floor(
dayInQuarter(this.currentDate, this.timeframeItem.range) /
totalDaysInQuarter(this.timeframeItem.range) *
(dayInQuarter(this.currentDate, this.timeframeItem.range) /
totalDaysInQuarter(this.timeframeItem.range)) *
100,
);
} else if (this.presetType === PRESET_TYPES.MONTHS) {
left = Math.floor(this.currentDate.getDate() / totalDaysInMonth(this.timeframeItem) * 100);
left = Math.floor(
(this.currentDate.getDate() / totalDaysInMonth(this.timeframeItem)) * 100,
);
} else if (this.presetType === PRESET_TYPES.WEEKS) {
left = Math.floor(((this.currentDate.getDay() + 1) / 7 * 100) - 7);
left = Math.floor(((this.currentDate.getDay() + 1) / 7) * 100 - 7);
}
// We add 20 to height to ensure that
......@@ -73,7 +75,7 @@ export default {
const rootOffsetLeft = this.$root.$el.offsetLeft;
// 3px to compensate size of bubble on top of Indicator
this.todayBarReady = (indicatorX - rootOffsetLeft) >= (EPIC_DETAILS_CELL_WIDTH + 3);
this.todayBarReady = indicatorX - rootOffsetLeft >= EPIC_DETAILS_CELL_WIDTH + 3;
},
},
};
......
......@@ -25,17 +25,29 @@ export const PRESET_TYPES = {
export const PRESET_DEFAULTS = {
QUARTERS: {
TIMEFRAME_LENGTH: 18,
emptyStateDefault: s__('GroupRoadmap|To view the roadmap, add a start or due date to one of your epics in this group or its subgroups. In the quarters view, only epics in the past quarter, current quarter, and next 4 quarters are shown &ndash; from %{startDate} to %{endDate}.'),
emptyStateWithFilters: s__('GroupRoadmap|To widen your search, change or remove filters. In the quarters view, only epics in the past quarter, current quarter, and next 4 quarters are shown &ndash; from %{startDate} to %{endDate}.'),
emptyStateDefault: s__(
'GroupRoadmap|To view the roadmap, add a start or due date to one of your epics in this group or its subgroups. In the quarters view, only epics in the past quarter, current quarter, and next 4 quarters are shown &ndash; from %{startDate} to %{endDate}.',
),
emptyStateWithFilters: s__(
'GroupRoadmap|To widen your search, change or remove filters. In the quarters view, only epics in the past quarter, current quarter, and next 4 quarters are shown &ndash; from %{startDate} to %{endDate}.',
),
},
MONTHS: {
TIMEFRAME_LENGTH: 7,
emptyStateDefault: s__('GroupRoadmap|To view the roadmap, add a start or due date to one of your epics in this group or its subgroups. In the months view, only epics in the past month, current month, and next 5 months are shown &ndash; from %{startDate} to %{endDate}.'),
emptyStateWithFilters: s__('GroupRoadmap|To widen your search, change or remove filters. In the months view, only epics in the past month, current month, and next 5 months are shown &ndash; from %{startDate} to %{endDate}.'),
emptyStateDefault: s__(
'GroupRoadmap|To view the roadmap, add a start or due date to one of your epics in this group or its subgroups. In the months view, only epics in the past month, current month, and next 5 months are shown &ndash; from %{startDate} to %{endDate}.',
),
emptyStateWithFilters: s__(
'GroupRoadmap|To widen your search, change or remove filters. In the months view, only epics in the past month, current month, and next 5 months are shown &ndash; from %{startDate} to %{endDate}.',
),
},
WEEKS: {
TIMEFRAME_LENGTH: 42,
emptyStateDefault: s__('GroupRoadmap|To view the roadmap, add a start or due date to one of your epics in this group or its subgroups. In the weeks view, only epics in the past week, current week, and next 4 weeks are shown &ndash; from %{startDate} to %{endDate}.'),
emptyStateWithFilters: s__('GroupRoadmap|To widen your search, change or remove filters. In the weeks view, only epics in the past week, current week, and next 4 weeks are shown &ndash; from %{startDate} to %{endDate}.'),
emptyStateDefault: s__(
'GroupRoadmap|To view the roadmap, add a start or due date to one of your epics in this group or its subgroups. In the weeks view, only epics in the past week, current week, and next 4 weeks are shown &ndash; from %{startDate} to %{endDate}.',
),
emptyStateWithFilters: s__(
'GroupRoadmap|To widen your search, change or remove filters. In the weeks view, only epics in the past week, current week, and next 4 weeks are shown &ndash; from %{startDate} to %{endDate}.',
),
},
};
......@@ -73,7 +73,7 @@ export default {
}
// Calculate proportional offset based on startDate and total days in
// current month.
return `left: ${startDate / daysInMonth * 100}%;`;
return `left: ${(startDate / daysInMonth) * 100}%;`;
},
/**
* This method is externally only called when current timeframe cell has timeline
......
......@@ -65,7 +65,7 @@ export default {
return `right: ${TIMELINE_END_OFFSET_HALF}px;`;
}
return `left: ${startDay / daysInQuarter * 100}%;`;
return `left: ${(startDay / daysInQuarter) * 100}%;`;
},
/**
* This method is externally only called when current timeframe cell has timeline
......
......@@ -23,7 +23,7 @@ export default {
return Math.max(width, TIMELINE_CELL_MIN_WIDTH);
},
sectionContainerStyles() {
const width = EPIC_DETAILS_CELL_WIDTH + (this.sectionItemWidth * this.timeframe.length);
const width = EPIC_DETAILS_CELL_WIDTH + this.sectionItemWidth * this.timeframe.length;
return {
width: `${width}px`,
};
......
......@@ -43,7 +43,7 @@ export default {
*/
getTimelineBarEndOffsetHalfForWeek() {
const dayWidth = this.getCellWidth() / 7;
return TIMELINE_END_OFFSET_HALF + (dayWidth * 0.5);
return TIMELINE_END_OFFSET_HALF + dayWidth * 0.5;
},
/**
* In case startDate for any epic is undefined or is out of range
......@@ -82,7 +82,7 @@ export default {
return `right: ${TIMELINE_END_OFFSET_HALF}px;`;
}
return `left: ${(startDate * dayWidth) - (dayWidth / 2)}px;`;
return `left: ${startDate * dayWidth - dayWidth / 2}px;`;
},
/**
* This method is externally only called when current timeframe cell has timeline
......
......@@ -4,8 +4,9 @@ import vulnerabilities from './modules/vulnerabilities/index';
Vue.use(Vuex);
export default () => new Vuex.Store({
export default () =>
new Vuex.Store({
modules: {
vulnerabilities,
},
});
});
<script>
import { __ } from '~/locale';
import tooltip from '~/vue_shared/directives/tooltip';
import { spriteIcon } from '~/lib/utils/common_utils';
import Store from '../stores/sidebar_store';
import { __ } from '~/locale';
import tooltip from '~/vue_shared/directives/tooltip';
import { spriteIcon } from '~/lib/utils/common_utils';
import Store from '../stores/sidebar_store';
export default {
export default {
name: 'SidebarItemEpic',
directives: {
tooltip,
......@@ -41,14 +41,18 @@
if (this.store.epic.human_readable_end_date || this.store.epic.human_readable_timestamp) {
tooltipTitle += '<br />';
tooltipTitle += this.store.epic.human_readable_end_date ? `${this.store.epic.human_readable_end_date} ` : '';
tooltipTitle += this.store.epic.human_readable_timestamp ? `(${this.store.epic.human_readable_timestamp})` : '';
tooltipTitle += this.store.epic.human_readable_end_date
? `${this.store.epic.human_readable_end_date} `
: '';
tooltipTitle += this.store.epic.human_readable_timestamp
? `(${this.store.epic.human_readable_timestamp})`
: '';
}
return tooltipTitle;
},
},
};
};
</script>
<template>
......
......@@ -14,7 +14,8 @@ function mountWeightComponent(mediator) {
components: {
sidebarWeight,
},
render: createElement => createElement('sidebar-weight', {
render: createElement =>
createElement('sidebar-weight', {
props: {
mediator,
},
......
......@@ -15,13 +15,14 @@ export default class SidebarMediator extends CESidebarMediator {
updateWeight(newWeight) {
this.store.setLoadingState('weight', true);
return this.service.update('issue[weight]', newWeight)
return this.service
.update('issue[weight]', newWeight)
.then(res => res.json())
.then((data) => {
.then(data => {
this.store.setWeight(data.weight);
this.store.setLoadingState('weight', false);
})
.catch((err) => {
.catch(err => {
this.store.setLoadingState('weight', false);
throw err;
});
......
......@@ -2,7 +2,11 @@ import $ from 'jquery';
const snowPlowEnabled = () => typeof window.snowplow === 'function';
const trackEvent = (category, eventName, additionalData = { label: '', property: '', value: '' }) => {
const trackEvent = (
category,
eventName,
additionalData = { label: '', property: '', value: '' },
) => {
if (!snowPlowEnabled()) {
return;
}
......@@ -14,14 +18,7 @@ const trackEvent = (category, eventName, additionalData = { label: '', property:
const { label, property, value } = additionalData;
try {
window.snowplow(
'trackStructEvent',
category,
eventName,
label,
property,
value,
);
window.snowplow('trackStructEvent', category, eventName, label, property, value);
} catch (e) {
// do nothing
}
......@@ -32,7 +29,7 @@ const bindTrackableContainer = (container = '', category = document.body.dataset
return;
}
const clickHandler = (e) => {
const clickHandler = e => {
const target = e.currentTarget;
const label = target.getAttribute('data-track-label');
const property = target.getAttribute('data-track-property') || '';
......@@ -45,7 +42,10 @@ const bindTrackableContainer = (container = '', category = document.body.dataset
}
// overrides value if data-track_value is set
if (typeof target.getAttribute('data-track-value') !== 'undefined' && target.getAttribute('data-track-value') !== null) {
if (
typeof target.getAttribute('data-track-value') !== 'undefined' &&
target.getAttribute('data-track-value') !== null
) {
value = target.getAttribute('data-track-value');
}
......@@ -54,12 +54,12 @@ const bindTrackableContainer = (container = '', category = document.body.dataset
const trackableElements = document.querySelectorAll(`${container} [data-track-label]`);
trackableElements.forEach(element => {
element.addEventListener('click', (e) => clickHandler(e));
element.addEventListener('click', e => clickHandler(e));
});
// jquery required for select2 events
// see: https://github.com/select2/select2/issues/4686#issuecomment-264747428
$(`${container} .select2[data-track-label]`).on('click', (e) => clickHandler(e));
$(`${container} .select2[data-track-label]`).on('click', e => clickHandler(e));
};
export default {
......
......@@ -71,9 +71,9 @@ export default {
}
if (this.approvalsLeft === 0) {
return this.userCanApprove ?
s__('mrWidget|Merge request approved; you can approve additionally') :
s__('mrWidget|Merge request approved');
return this.userCanApprove
? s__('mrWidget|Merge request approved; you can approve additionally')
: s__('mrWidget|Merge request approved');
}
if (this.suggestedApprovers.length >= 1) {
......
<script>
import icon from '~/vue_shared/components/icon.vue';
import ciStatus from '~/vue_shared/components/ci_icon.vue';
import tooltip from '~/vue_shared/directives/tooltip';
import icon from '~/vue_shared/components/icon.vue';
import ciStatus from '~/vue_shared/components/ci_icon.vue';
import tooltip from '~/vue_shared/directives/tooltip';
export default {
export default {
directives: {
tooltip,
},
......@@ -48,9 +48,9 @@
return this.linkedPipelines.length;
},
linkedPipelinesTrimmed() {
return (this.totalPipelineCount > this.maxRenderedPipelines) ?
this.linkedPipelines.slice(0, this.maxRenderedPipelines) :
this.linkedPipelines;
return this.totalPipelineCount > this.maxRenderedPipelines
? this.linkedPipelines.slice(0, this.maxRenderedPipelines)
: this.linkedPipelines;
},
shouldRenderCounter() {
return this.isDownstream && this.linkedPipelines.length > this.maxRenderedPipelines;
......@@ -73,7 +73,7 @@
return `ci-status-icon-${group}`;
},
},
};
};
</script>
<template>
......
......@@ -9,9 +9,7 @@ export const licenseReport = state =>
export const licenseSummaryText = (state, getters) => {
const hasReportItems = getters.licenseReport && getters.licenseReport.length;
const baseReportHasLicenses =
state.baseReport
&& state.baseReport.licenses
&& state.baseReport.licenses.length;
state.baseReport && state.baseReport.licenses && state.baseReport.licenses.length;
if (getters.isLoading) {
return sprintf(s__('ciReport|Loading %{reportName} report'), {
......
import { n__, sprintf } from '~/locale';
import {
STATUS_FAILED,
STATUS_NEUTRAL,
STATUS_SUCCESS,
} from '~/reports/constants';
import { STATUS_FAILED, STATUS_NEUTRAL, STATUS_SUCCESS } from '~/reports/constants';
import { LICENSE_APPROVAL_STATUS } from 'ee/vue_shared/license_management/constants';
/**
......
import {
LOADING,
ERROR,
SUCCESS,
} from '../store/constants';
import { LOADING, ERROR, SUCCESS } from '../store/constants';
export default {
methods: {
......
......@@ -4,7 +4,9 @@ export default {
computed: {
sastPopover() {
return {
title: s__('ciReport|Static Application Security Testing (SAST) detects known vulnerabilities in your source code.'),
title: s__(
'ciReport|Static Application Security Testing (SAST) detects known vulnerabilities in your source code.',
),
content: sprintf(
s__('ciReport|%{linkStartTag}Learn more about SAST %{linkEndTag}'),
{
......@@ -17,7 +19,9 @@ export default {
},
sastContainerPopover() {
return {
title: s__('ciReport|Container scanning detects known vulnerabilities in your docker images.'),
title: s__(
'ciReport|Container scanning detects known vulnerabilities in your docker images.',
),
content: sprintf(
s__('ciReport|%{linkStartTag}Learn more about Container Scanning %{linkEndTag}'),
{
......@@ -30,7 +34,9 @@ export default {
},
dastPopover() {
return {
title: s__('ciReport|Dynamic Application Security Testing (DAST) detects known vulnerabilities in your web application.'),
title: s__(
'ciReport|Dynamic Application Security Testing (DAST) detects known vulnerabilities in your web application.',
),
content: sprintf(
s__('ciReport|%{linkStartTag}Learn more about DAST %{linkEndTag}'),
{
......@@ -43,7 +49,9 @@ export default {
},
dependencyScanningPopover() {
return {
title: s__('ciReport|Dependency Scanning detects known vulnerabilities in your source code\'s dependencies.'),
title: s__(
"ciReport|Dependency Scanning detects known vulnerabilities in your source code's dependencies.",
),
content: sprintf(
s__('ciReport|%{linkStartTag}Learn more about Dependency Scanning %{linkEndTag}'),
{
......
......@@ -7,9 +7,10 @@ import state from './state';
Vue.use(Vuex);
export default () => new Vuex.Store({
export default () =>
new Vuex.Store({
actions,
getters,
mutations,
state: state(),
});
});
......@@ -230,10 +230,16 @@ export default {
[types.RECEIVE_DEPENDENCY_SCANNING_REPORTS](state, reports) {
if (reports.base && reports.head) {
const filterKey = 'cve';
const parsedHead = parseDependencyScanningIssues(reports.head, reports.enrichData,
state.blobPath.head);
const parsedBase = parseDependencyScanningIssues(reports.base, reports.enrichData,
state.blobPath.base);
const parsedHead = parseDependencyScanningIssues(
reports.head,
reports.enrichData,
state.blobPath.head,
);
const parsedBase = parseDependencyScanningIssues(
reports.base,
reports.enrichData,
state.blobPath.base,
);
const newIssues = filterByKey(parsedHead, parsedBase, filterKey);
const resolvedIssues = filterByKey(parsedBase, parsedHead, filterKey);
......@@ -250,8 +256,11 @@ export default {
}
if (reports.head && !reports.base) {
const newIssues = parseDependencyScanningIssues(reports.head, reports.enrichData,
state.blobPath.head);
const newIssues = parseDependencyScanningIssues(
reports.head,
reports.enrichData,
state.blobPath.head,
);
Vue.set(state.dependencyScanning, 'newIssues', newIssues);
Vue.set(state.dependencyScanning, 'isLoading', false);
......
......@@ -18,9 +18,9 @@ export const findIssueIndex = (issues, issue) =>
* @param {Array} feedback
*/
function enrichVulnerabilityWithfeedback(vulnerability, feedback = []) {
return feedback.filter(
fb => fb.project_fingerprint === vulnerability.project_fingerprint,
).reduce((vuln, fb) => {
return feedback
.filter(fb => fb.project_fingerprint === vulnerability.project_fingerprint)
.reduce((vuln, fb) => {
if (fb.feedback_type === 'dismissal') {
return {
...vuln,
......@@ -155,24 +155,30 @@ export const parseSastContainer = (issues = [], feedback = []) =>
const parsed = {
...issue,
category: 'container_scanning',
project_fingerprint: sha1(`${issue.namespace}:${issue.vulnerability}:${issue.featurename}:${issue.featureversion}`),
project_fingerprint: sha1(
`${issue.namespace}:${issue.vulnerability}:${issue.featurename}:${issue.featureversion}`,
),
title: issue.vulnerability,
description: !_.isEmpty(issue.description) ? issue.description :
sprintf(s__('ciReport|%{namespace} is affected by %{vulnerability}.'), {
description: !_.isEmpty(issue.description)
? issue.description
: sprintf(s__('ciReport|%{namespace} is affected by %{vulnerability}.'), {
namespace: issue.namespace,
vulnerability: issue.vulnerability,
}),
path: issue.namespace,
identifiers: [{
identifiers: [
{
type: 'CVE',
name: issue.vulnerability,
value: issue.vulnerability,
url: `https://cve.mitre.org/cgi-bin/cvename.cgi?name=${issue.vulnerability}`,
}],
},
],
};
// Generate solution
if (!_.isEmpty(issue.fixedby) &&
if (
!_.isEmpty(issue.fixedby) &&
!_.isEmpty(issue.featurename) &&
!_.isEmpty(issue.featureversion)
) {
......@@ -213,12 +219,14 @@ export const parseDastIssues = (issues = [], feedback = []) =>
if (!_.isEmpty(issue.cweid)) {
Object.assign(parsed, {
identifiers: [{
identifiers: [
{
type: 'CWE',
name: `CWE-${issue.cweid}`,
value: issue.cweid,
url: `https://cwe.mitre.org/data/definitions/${issue.cweid}.html`,
}],
},
],
});
}
......
......@@ -6,7 +6,15 @@ function WeightSelect(els, options = {}) {
const $els = $(els || '.js-weight-select');
$els.each(function(i, dropdown) {
var $block, $dropdown, $loading, $selectbox, $sidebarCollapsedValue, $value, abilityName, updateUrl, updateWeight;
var $block,
$dropdown,
$loading,
$selectbox,
$sidebarCollapsedValue,
$value,
abilityName,
updateUrl,
updateWeight;
$dropdown = $(dropdown);
updateUrl = $dropdown.data('issueUpdate');
$selectbox = $dropdown.closest('.selectbox');
......@@ -15,7 +23,7 @@ function WeightSelect(els, options = {}) {
$value = $block.find('.value');
abilityName = $dropdown.data('abilityName');
$loading = $block.find('.block-loading').fadeOut();
const fieldName = options.fieldName || $dropdown.data("fieldName");
const fieldName = options.fieldName || $dropdown.data('fieldName');
const inputField = $dropdown.closest('.selectbox').find(`input[name='${fieldName}']`);
if (Object.keys(options).includes('selected')) {
......@@ -25,16 +33,16 @@ function WeightSelect(els, options = {}) {
return $dropdown.glDropdown({
selectable: true,
fieldName,
toggleLabel: function (selected, el) {
return $(el).data("id");
toggleLabel: function(selected, el) {
return $(el).data('id');
},
hidden: function(e) {
$selectbox.hide();
return $value.css('display', '');
},
id: function(obj, el) {
if ($(el).data("none") == null) {
return $(el).data("id");
if ($(el).data('none') == null) {
return $(el).data('id');
} else {
return '';
}
......@@ -51,7 +59,7 @@ function WeightSelect(els, options = {}) {
} else if ($dropdown.is('.js-issuable-form-weight')) {
e.preventDefault();
}
}
},
});
});
}
......
......@@ -11,13 +11,16 @@ describe('AddGitlabSlackApplication', () => {
const docsPath = '//docsPath';
const gitlabLogoPath = '//gitlabLogoPath';
const slackLogoPath = '//slackLogoPath';
const projects = [{
const projects = [
{
id: 4,
name: 'test',
}, {
},
{
id: 6,
name: 'nope',
}];
},
];
const DEFAULT_PROPS = {
projects,
gitlabForSlackGifPath,
......@@ -31,20 +34,20 @@ describe('AddGitlabSlackApplication', () => {
const AddGitlabSlackApplication = Vue.extend(addGitlabSlackApplication);
it('opens popup when button is clicked', (done) => {
it('opens popup when button is clicked', done => {
const vm = mountComponent(AddGitlabSlackApplication, DEFAULT_PROPS);
vm.$el.querySelector('.js-popup-button').click();
vm.$nextTick()
.then(() => {
expect(vm.$el.querySelector('.js-popup')).toBeDefined()
expect(vm.$el.querySelector('.js-popup')).toBeDefined();
})
.then(done)
.catch(done.fail);
});
it('hides popup when button is clicked', (done) => {
it('hides popup when button is clicked', done => {
const vm = mountComponent(AddGitlabSlackApplication, DEFAULT_PROPS);
vm.popupOpen = true;
......@@ -53,13 +56,13 @@ describe('AddGitlabSlackApplication', () => {
.then(() => vm.$el.querySelector('.js-popup-button').click())
.then(vm.$nextTick)
.then(() => {
expect(vm.$el.querySelector('.js-popup')).toBeNull()
expect(vm.$el.querySelector('.js-popup')).toBeNull();
})
.then(done)
.catch(done.fail);
});
it('popup has a project select when signed in', (done) => {
it('popup has a project select when signed in', done => {
const vm = mountComponent(AddGitlabSlackApplication, {
...DEFAULT_PROPS,
isSignedIn: true,
......@@ -69,13 +72,13 @@ describe('AddGitlabSlackApplication', () => {
vm.$nextTick()
.then(() => {
expect(vm.$el.querySelector('.js-project-select')).toBeDefined()
expect(vm.$el.querySelector('.js-project-select')).toBeDefined();
})
.then(done)
.catch(done.fail);
});
it('popup has a message when there is no projects', (done) => {
it('popup has a message when there is no projects', done => {
const vm = mountComponent(AddGitlabSlackApplication, {
...DEFAULT_PROPS,
projects: [],
......@@ -86,14 +89,15 @@ describe('AddGitlabSlackApplication', () => {
vm.$nextTick()
.then(() => {
expect(vm.$el.querySelector('.js-no-projects').textContent)
.toMatch("You don't have any projects available.");
expect(vm.$el.querySelector('.js-no-projects').textContent).toMatch(
"You don't have any projects available.",
);
})
.then(done)
.catch(done.fail);
});
it('popup has a sign in link when logged out', (done) => {
it('popup has a sign in link when logged out', done => {
const vm = mountComponent(AddGitlabSlackApplication, {
...DEFAULT_PROPS,
});
......@@ -103,14 +107,15 @@ describe('AddGitlabSlackApplication', () => {
vm.$nextTick()
.then(() => {
expect(vm.$el.querySelector('.js-gitlab-slack-sign-in-link').href)
.toMatch(new RegExp(signInPath, 'i'));
expect(vm.$el.querySelector('.js-gitlab-slack-sign-in-link').href).toMatch(
new RegExp(signInPath, 'i'),
);
})
.then(done)
.catch(done.fail);
});
it('redirects user to external link when submitted', (done) => {
it('redirects user to external link when submitted', done => {
const vm = mountComponent(AddGitlabSlackApplication, {
...DEFAULT_PROPS,
isSignedIn: true,
......@@ -127,7 +132,7 @@ describe('AddGitlabSlackApplication', () => {
.then(vm.$nextTick)
.then(addToSlackPromise)
.then(() => {
expect(redirectTo).toHaveBeenCalledWith(redirectLink)
expect(redirectTo).toHaveBeenCalledWith(redirectLink);
})
.then(done)
.catch(done.fail);
......
......@@ -98,8 +98,9 @@ describe('Approvals Body Component', () => {
vm.userCanApprove = true;
Vue.nextTick(() => {
expect(vm.approvalsRequiredStringified)
.toBe('Merge request approved; you can approve additionally');
expect(vm.approvalsRequiredStringified).toBe(
'Merge request approved; you can approve additionally',
);
done();
});
});
......
......@@ -114,8 +114,7 @@ describe('Batch comments draft note component', () => {
it('dispatches updateDraft', done => {
vm.$el.querySelector('.js-note-edit').click();
vm
.$nextTick()
vm.$nextTick()
.then(() => {
vm.$el.querySelector('.js-vue-issue-save').click();
......
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
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