Skip to content
Snippets Groups Projects
Commit dba86447 authored by GitLab Bot's avatar GitLab Bot
Browse files

Add latest changes from gitlab-org/gitlab@12-8-stable-ee

parent b7d29500
No related branches found
No related tags found
No related merge requests found
Showing
with 389 additions and 46 deletions
/* eslint-disable no-shadow */
/* eslint-disable no-shadow, no-param-reassign */
/* global List */
 
import $ from 'jquery';
Loading
Loading
@@ -131,6 +131,53 @@ const boardsStore = {
listFrom.update();
},
 
addMultipleListIssues(list, issues, listFrom, newIndex) {
let moveBeforeId = null;
let moveAfterId = null;
const listHasIssues = issues.every(issue => list.findIssue(issue.id));
if (!listHasIssues) {
if (newIndex !== undefined) {
if (list.issues[newIndex - 1]) {
moveBeforeId = list.issues[newIndex - 1].id;
}
if (list.issues[newIndex]) {
moveAfterId = list.issues[newIndex].id;
}
list.issues.splice(newIndex, 0, ...issues);
} else {
list.issues.push(...issues);
}
if (list.label) {
issues.forEach(issue => issue.addLabel(list.label));
}
if (list.assignee) {
if (listFrom && listFrom.type === 'assignee') {
issues.forEach(issue => issue.removeAssignee(listFrom.assignee));
}
issues.forEach(issue => issue.addAssignee(list.assignee));
}
if (IS_EE && list.milestone) {
if (listFrom && listFrom.type === 'milestone') {
issues.forEach(issue => issue.removeMilestone(listFrom.milestone));
}
issues.forEach(issue => issue.addMilestone(list.milestone));
}
if (listFrom) {
list.issuesSize += issues.length;
list.updateMultipleIssues(issues, listFrom, moveBeforeId, moveAfterId);
}
}
},
startMoving(list, issue) {
Object.assign(this.moving, { list, issue });
},
Loading
Loading
@@ -408,6 +455,29 @@ const boardsStore = {
return axios.delete(`${this.state.endpoints.listsEndpoint}/${id}`);
},
 
saveList(list) {
const entity = list.label || list.assignee || list.milestone;
let entityType = '';
if (list.label) {
entityType = 'label_id';
} else if (list.assignee) {
entityType = 'assignee_id';
} else if (IS_EE && list.milestone) {
entityType = 'milestone_id';
}
return this.createList(entity.id, entityType)
.then(res => res.data)
.then(data => {
list.id = data.id;
list.type = data.list_type;
list.position = data.position;
list.label = data.label;
return list.getIssues();
});
},
getIssuesForList(id, filter = {}) {
const data = { id };
Object.keys(filter).forEach(key => {
Loading
Loading
import Cookies from 'js-cookie';
const handleOnDismiss = ({ currentTarget }) => {
currentTarget.removeEventListener('click', handleOnDismiss);
const {
dataset: { id },
} = currentTarget;
Cookies.set(`hide_broadcast_notification_message_${id}`, true);
const notification = document.querySelector(`.js-broadcast-notification-${id}`);
notification.parentNode.removeChild(notification);
};
export default () => {
const dismissButton = document.querySelector('.js-dismiss-current-broadcast-notification');
if (dismissButton) {
dismissButton.addEventListener('click', handleOnDismiss);
}
};
import _ from 'underscore';
import { escape as esc } from 'lodash';
import axios from '../lib/utils/axios_utils';
import { s__ } from '../locale';
import Flash from '../flash';
Loading
Loading
@@ -10,7 +10,7 @@ function generateErrorBoxContent(errors) {
const errorList = [].concat(errors).map(
errorString => `
<li>
${_.escape(errorString)}
${esc(errorString)}
</li>
`,
);
Loading
Loading
Loading
Loading
@@ -307,7 +307,7 @@ export default {
<a
v-if="titleLink"
:href="titleLink"
target="blank"
target="_blank"
rel="noopener noreferrer"
class="js-cluster-application-title"
>{{ title }}</a
Loading
Loading
Loading
Loading
@@ -129,9 +129,6 @@ export default {
crossplaneInstalled() {
return this.applications.crossplane.status === APPLICATION_STATUS.INSTALLED;
},
enableClusterApplicationElasticStack() {
return gon.features && gon.features.enableClusterApplicationElasticStack;
},
ingressModSecurityDescription() {
const escapedUrl = _.escape(this.ingressModSecurityHelpPath);
 
Loading
Loading
@@ -655,7 +652,6 @@ Crossplane runs inside your Kubernetes cluster and supports secure connectivity
</div>
</application-row>
<application-row
v-if="enableClusterApplicationElasticStack"
id="elastic_stack"
:logo-url="elasticStackLogo"
:title="applications.elastic_stack.title"
Loading
Loading
Loading
Loading
@@ -257,6 +257,7 @@ export default class ClusterStore {
name: environment.name,
project: environment.project,
environmentPath: environment.environment_path,
logsPath: environment.logs_path,
lastDeployment: environment.last_deployment,
rolloutStatus: {
status: environment.rollout_status ? environment.rollout_status.status : null,
Loading
Loading
<script>
import { mapActions, mapState } from 'vuex';
import Popover from './popover.vue';
export default {
components: {
Popover,
},
computed: {
...mapState(['currentDefinition', 'currentDefinitionPosition']),
},
mounted() {
this.blobViewer = document.querySelector('.blob-viewer');
this.addGlobalEventListeners();
this.fetchData();
},
beforeDestroy() {
this.removeGlobalEventListeners();
},
methods: {
...mapActions(['fetchData', 'showDefinition']),
addGlobalEventListeners() {
if (this.blobViewer) {
this.blobViewer.addEventListener('click', this.showDefinition);
}
},
removeGlobalEventListeners() {
if (this.blobViewer) {
this.blobViewer.removeEventListener('click', this.showDefinition);
}
},
},
};
</script>
<template>
<popover
v-if="currentDefinition"
:position="currentDefinitionPosition"
:data="currentDefinition"
/>
</template>
<script>
import { GlButton } from '@gitlab/ui';
export default {
components: {
GlButton,
},
props: {
position: {
type: Object,
required: true,
},
data: {
type: Object,
required: true,
},
},
data() {
return {
offsetLeft: 0,
};
},
computed: {
positionStyles() {
return {
left: `${this.position.x - this.offsetLeft}px`,
top: `${this.position.y + this.position.height}px`,
};
},
},
watch: {
position: {
handler() {
this.$nextTick(() => this.updateOffsetLeft());
},
deep: true,
immediate: true,
},
},
methods: {
updateOffsetLeft() {
this.offsetLeft = Math.max(
0,
this.$el.offsetLeft + this.$el.offsetWidth - window.innerWidth + 20,
);
},
},
colorScheme: gon?.user_color_scheme,
};
</script>
<template>
<div
:style="positionStyles"
class="popover code-navigation-popover popover-font-size-normal gl-popover bs-popover-bottom show"
>
<div :style="{ left: `${offsetLeft}px` }" class="arrow"></div>
<div v-for="(hover, index) in data.hover" :key="index" class="border-bottom">
<pre
v-if="hover.language"
ref="code-output"
:class="$options.colorScheme"
class="border-0 bg-transparent m-0 code highlight"
v-html="hover.value"
></pre>
<p v-else ref="doc-output" class="p-3 m-0">
{{ hover.value }}
</p>
</div>
<div v-if="data.definition_url" class="popover-body">
<gl-button :href="data.definition_url" target="_blank" class="w-100" variant="default">
{{ __('Go to definition') }}
</gl-button>
</div>
</div>
</template>
import Vue from 'vue';
import Vuex from 'vuex';
import store from './store';
import App from './components/app.vue';
Vue.use(Vuex);
export default () => {
const el = document.getElementById('js-code-navigation');
store.dispatch('setInitialData', el.dataset);
return new Vue({
el,
store,
render(h) {
return h(App);
},
});
};
import api from '~/api';
import * as types from './mutation_types';
import { getCurrentHoverElement, setCurrentHoverElement, addInteractionClass } from '../utils';
export default {
setInitialData({ commit }, data) {
commit(types.SET_INITIAL_DATA, data);
},
requestDataError({ commit }) {
commit(types.REQUEST_DATA_ERROR);
},
fetchData({ commit, dispatch, state }) {
commit(types.REQUEST_DATA);
api
.lsifData(state.projectPath, state.commitId, state.blobPath)
.then(({ data }) => {
const normalizedData = data.reduce((acc, d) => {
if (d.hover) {
acc[`${d.start_line}:${d.start_char}`] = d;
addInteractionClass(d);
}
return acc;
}, {});
commit(types.REQUEST_DATA_SUCCESS, normalizedData);
})
.catch(() => dispatch('requestDataError'));
},
showDefinition({ commit, state }, { target: el }) {
let definition;
let position;
if (!state.data) return;
const isCurrentElementPopoverOpen = el.classList.contains('hll');
if (getCurrentHoverElement()) {
getCurrentHoverElement().classList.remove('hll');
}
if (el.classList.contains('js-code-navigation') && !isCurrentElementPopoverOpen) {
const { lineIndex, charIndex } = el.dataset;
position = {
x: el.offsetLeft,
y: el.offsetTop,
height: el.offsetHeight,
};
definition = state.data[`${lineIndex}:${charIndex}`];
el.classList.add('hll');
setCurrentHoverElement(el);
}
commit(types.SET_CURRENT_DEFINITION, { definition, position });
},
};
import Vuex from 'vuex';
import createState from './state';
import actions from './actions';
import mutations from './mutations';
export default new Vuex.Store({
actions,
mutations,
state: createState(),
});
export const SET_INITIAL_DATA = 'SET_INITIAL_DATA';
export const REQUEST_DATA = 'REQUEST_DATA';
export const REQUEST_DATA_SUCCESS = 'REQUEST_DATA_SUCCESS';
export const REQUEST_DATA_ERROR = 'REQUEST_DATA_ERROR';
export const SET_CURRENT_DEFINITION = 'SET_CURRENT_DEFINITION';
import * as types from './mutation_types';
export default {
[types.SET_INITIAL_DATA](state, { projectPath, commitId, blobPath }) {
state.projectPath = projectPath;
state.commitId = commitId;
state.blobPath = blobPath;
},
[types.REQUEST_DATA](state) {
state.loading = true;
},
[types.REQUEST_DATA_SUCCESS](state, data) {
state.loading = false;
state.data = data;
},
[types.REQUEST_DATA_ERROR](state) {
state.loading = false;
},
[types.SET_CURRENT_DEFINITION](state, { definition, position }) {
state.currentDefinition = definition;
state.currentDefinitionPosition = position;
},
};
export default () => ({
projectPath: null,
commitId: null,
blobPath: null,
loading: false,
data: null,
currentDefinition: null,
currentDefinitionPosition: null,
});
export const cachedData = new Map();
export const getCurrentHoverElement = () => cachedData.get('current');
export const setCurrentHoverElement = el => cachedData.set('current', el);
export const addInteractionClass = d => {
let charCount = 0;
const line = document.getElementById(`LC${d.start_line + 1}`);
const el = [...line.childNodes].find(({ textContent }) => {
if (charCount === d.start_char) return true;
charCount += textContent.length;
return false;
});
if (el) {
el.setAttribute('data-char-index', d.start_char);
el.setAttribute('data-line-index', d.start_line);
el.classList.add('cursor-pointer', 'code-navigation', 'js-code-navigation');
}
};
Loading
Loading
@@ -4,6 +4,6 @@ import 'jquery';
import 'jquery-ujs';
import 'vendor/jquery.endless-scroll';
import 'jquery.caret'; // must be imported before at.js
import 'at.js';
import '@gitlab/at.js';
import 'vendor/jquery.scrollTo';
import 'jquery.waitforimages';
// ECMAScript polyfills
import 'core-js/es/array/fill';
import 'core-js/es/array/find';
import 'core-js/es/array/find-index';
import 'core-js/es/array/from';
import 'core-js/es/array/includes';
import 'core-js/es/number/is-integer';
import 'core-js/es/object/assign';
import 'core-js/es/object/values';
import 'core-js/es/object/entries';
import 'core-js/es/promise';
import 'core-js/es/promise/finally';
import 'core-js/es/string/code-point-at';
import 'core-js/es/string/from-code-point';
import 'core-js/es/string/includes';
import 'core-js/es/string/starts-with';
import 'core-js/es/string/ends-with';
import 'core-js/es/symbol';
import 'core-js/es/map';
import 'core-js/es/weak-map';
import 'core-js/modules/web.url';
// Browser polyfills
import 'formdata-polyfill';
import './polyfills/custom_event';
Loading
Loading
<script>
import _ from 'underscore';
import { debounce, uniq } from 'lodash';
import { mapActions, mapState, mapGetters } from 'vuex';
import { GlLoadingIcon } from '@gitlab/ui';
import { GlAreaChart } from '@gitlab/ui/dist/charts';
Loading
Loading
@@ -7,11 +7,13 @@ import { __ } from '~/locale';
import { getSvgIconPathContent } from '~/lib/utils/icon_utils';
import { getDatesInRange } from '~/lib/utils/datetime_utility';
import { xAxisLabelFormatter, dateFormatter } from '../utils';
import ResizableChartContainer from '~/vue_shared/components/resizable_chart/resizable_chart_container.vue';
 
export default {
components: {
GlAreaChart,
GlLoadingIcon,
ResizableChartContainer,
},
props: {
endpoint: {
Loading
Loading
@@ -118,7 +120,7 @@ export default {
return this.xAxisRange[this.xAxisRange.length - 1];
},
charts() {
return _.uniq(this.individualCharts);
return uniq(this.individualCharts);
},
},
mounted() {
Loading
Loading
@@ -169,7 +171,7 @@ export default {
});
})
.catch(() => {});
this.masterChart.on('datazoom', _.debounce(this.setIndividualChartsZoom, 200));
this.masterChart.on('datazoom', debounce(this.setIndividualChartsZoom, 200));
},
onIndividualChartCreated(chart) {
this.individualCharts.push(chart);
Loading
Loading
@@ -201,25 +203,35 @@ export default {
<div v-else-if="showChart" class="contributors-charts">
<h4>{{ __('Commits to') }} {{ branch }}</h4>
<span>{{ __('Excluding merge commits. Limited to 6,000 commits.') }}</span>
<div>
<resizable-chart-container>
<gl-area-chart
slot-scope="{ width }"
:width="width"
:data="masterChartData"
:option="masterChartOptions"
:height="masterChartHeight"
@created="onMasterChartCreated"
/>
</div>
</resizable-chart-container>
 
<div class="row">
<div v-for="contributor in individualChartsData" :key="contributor.name" class="col-6">
<div
v-for="(contributor, index) in individualChartsData"
:key="index"
class="col-lg-6 col-12"
>
<h4>{{ contributor.name }}</h4>
<p>{{ n__('%d commit', '%d commits', contributor.commits) }} ({{ contributor.email }})</p>
<gl-area-chart
:data="contributor.dates"
:option="individualChartOptions"
:height="individualChartHeight"
@created="onIndividualChartCreated"
/>
<resizable-chart-container>
<gl-area-chart
slot-scope="{ width }"
:width="width"
:data="contributor.dates"
:option="individualChartOptions"
:height="individualChartHeight"
@created="onIndividualChartCreated"
/>
</resizable-chart-container>
</div>
</div>
</div>
Loading
Loading
Loading
Loading
@@ -306,9 +306,9 @@ export default {
</script>
<template>
<form name="eks-cluster-configuration-form">
<h2>
<h4>
{{ s__('ClusterIntegration|Enter the details for your Amazon EKS Kubernetes cluster') }}
</h2>
</h4>
<div class="mb-3" v-html="kubernetesIntegrationHelpText"></div>
<div class="form-group">
<label class="label-bold" for="eks-cluster-name">{{
Loading
Loading
Loading
Loading
@@ -83,7 +83,7 @@ export default {
</script>
<template>
<form name="service-credentials-form">
<h2>{{ s__('ClusterIntegration|Authenticate with Amazon Web Services') }}</h2>
<h4>{{ s__('ClusterIntegration|Authenticate with Amazon Web Services') }}</h4>
<p>
{{
s__(
Loading
Loading
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment