Skip to content
Snippets Groups Projects
Commit cc502768 authored by John Jarvis's avatar John Jarvis
Browse files

Merge commit '207d3100' into 11-9-stable-prepare-rc4

parents 3190b498 207d3100
No related branches found
No related tags found
No related merge requests found
Showing
with 285 additions and 212 deletions
Loading
@@ -75,8 +75,7 @@ export const decorateData = entity => {
Loading
@@ -75,8 +75,7 @@ export const decorateData = entity => {
parentPath = '', parentPath = '',
} = entity; } = entity;
   
return { return Object.assign(dataStructure(), {
...dataStructure(),
id, id,
projectId, projectId,
branchId, branchId,
Loading
@@ -97,7 +96,7 @@ export const decorateData = entity => {
Loading
@@ -97,7 +96,7 @@ export const decorateData = entity => {
file_lock, file_lock,
html, html,
parentPath, parentPath,
}; });
}; };
   
export const findEntry = (tree, type, name, prop = 'name') => export const findEntry = (tree, type, name, prop = 'name') =>
Loading
Loading
import { viewerInformationForPath } from '~/vue_shared/components/content_viewer/lib/viewer_utils';
import { decorateData, sortTree } from '../utils';
// eslint-disable-next-line no-restricted-globals
self.addEventListener('message', e => {
const { data, projectId, branchId, tempFile = false, content = '', base64 = false } = e.data;
const treeList = [];
let file;
let parentPath;
const entries = data.reduce((acc, path) => {
const pathSplit = path.split('/');
const blobName = pathSplit.pop().trim();
if (pathSplit.length > 0) {
pathSplit.reduce((pathAcc, folderName) => {
const parentFolder = acc[pathAcc[pathAcc.length - 1]];
const folderPath = `${parentFolder ? `${parentFolder.path}/` : ''}${folderName}`;
const foundEntry = acc[folderPath];
if (!foundEntry) {
parentPath = parentFolder ? parentFolder.path : null;
const tree = decorateData({
projectId,
branchId,
id: folderPath,
name: folderName,
path: folderPath,
url: `/${projectId}/tree/${branchId}/-/${folderPath}/`,
type: 'tree',
parentTreeUrl: parentFolder ? parentFolder.url : `/${projectId}/tree/${branchId}/`,
tempFile,
changed: tempFile,
opened: tempFile,
parentPath,
});
Object.assign(acc, {
[folderPath]: tree,
});
if (parentFolder) {
parentFolder.tree.push(tree);
} else {
treeList.push(tree);
}
pathAcc.push(tree.path);
} else {
pathAcc.push(foundEntry.path);
}
return pathAcc;
}, []);
}
if (blobName !== '') {
const fileFolder = acc[pathSplit.join('/')];
parentPath = fileFolder ? fileFolder.path : null;
file = decorateData({
projectId,
branchId,
id: path,
name: blobName,
path,
url: `/${projectId}/blob/${branchId}/-/${path}`,
type: 'blob',
parentTreeUrl: fileFolder ? fileFolder.url : `/${projectId}/blob/${branchId}`,
tempFile,
changed: tempFile,
content,
base64,
previewMode: viewerInformationForPath(blobName),
parentPath,
});
Object.assign(acc, {
[path]: file,
});
if (fileFolder) {
fileFolder.tree.push(file);
} else {
treeList.push(file);
}
}
return acc;
}, {});
// eslint-disable-next-line no-restricted-globals
self.postMessage({
entries,
treeList: sortTree(treeList),
file,
parentPath,
});
});
Loading
@@ -34,6 +34,7 @@ export default {
Loading
@@ -34,6 +34,7 @@ export default {
StuckBlock, StuckBlock,
Sidebar, Sidebar,
GlLoadingIcon, GlLoadingIcon,
SharedRunner: () => import('ee_component/jobs/components/shared_runner_limit_block.vue'),
}, },
mixins: [delayedJobMixin], mixins: [delayedJobMixin],
props: { props: {
Loading
@@ -84,6 +85,7 @@ export default {
Loading
@@ -84,6 +85,7 @@ export default {
'shouldRenderCalloutMessage', 'shouldRenderCalloutMessage',
'shouldRenderTriggeredLabel', 'shouldRenderTriggeredLabel',
'hasEnvironment', 'hasEnvironment',
'shouldRenderSharedRunnerLimitWarning',
'hasTrace', 'hasTrace',
'emptyStateIllustration', 'emptyStateIllustration',
'isScrollingDown', 'isScrollingDown',
Loading
@@ -221,6 +223,14 @@ export default {
Loading
@@ -221,6 +223,14 @@ export default {
:runners-path="runnerSettingsUrl" :runners-path="runnerSettingsUrl"
/> />
   
<shared-runner
v-if="shouldRenderSharedRunnerLimitWarning"
class="js-shared-runner-limit"
:quota-used="job.runners.quota.used"
:quota-limit="job.runners.quota.limit"
:runners-path="runnerHelpUrl"
/>
<environments-block <environments-block
v-if="hasEnvironment" v-if="hasEnvironment"
class="js-job-environment" class="js-job-environment"
Loading
Loading
Loading
@@ -28,6 +28,17 @@ export const emptyStateIllustration = state =>
Loading
@@ -28,6 +28,17 @@ export const emptyStateIllustration = state =>
export const emptyStateAction = state => export const emptyStateAction = state =>
(state.job && state.job.status && state.job.status.action) || null; (state.job && state.job.status && state.job.status.action) || null;
   
/**
* Shared runners limit is only rendered when
* used quota is bigger or equal than the limit
*
* @returns {Boolean}
*/
export const shouldRenderSharedRunnerLimitWarning = state =>
!_.isEmpty(state.job.runners) &&
!_.isEmpty(state.job.runners.quota) &&
state.job.runners.quota.used >= state.job.runners.quota.limit;
export const isScrollingDown = state => isScrolledToBottom() && !state.isTraceComplete; export const isScrollingDown = state => isScrolledToBottom() && !state.isTraceComplete;
   
export const hasRunnersForProject = state => export const hasRunnersForProject = state =>
Loading
Loading
Loading
@@ -16,6 +16,7 @@ const httpStatusCodes = {
Loading
@@ -16,6 +16,7 @@ const httpStatusCodes = {
IM_USED: 226, IM_USED: 226,
MULTIPLE_CHOICES: 300, MULTIPLE_CHOICES: 300,
BAD_REQUEST: 400, BAD_REQUEST: 400,
UNAUTHORIZED: 401,
FORBIDDEN: 403, FORBIDDEN: 403,
NOT_FOUND: 404, NOT_FOUND: 404,
UNPROCESSABLE_ENTITY: 422, UNPROCESSABLE_ENTITY: 422,
Loading
Loading
Loading
@@ -4,6 +4,7 @@ import dateFormat from 'dateformat';
Loading
@@ -4,6 +4,7 @@ import dateFormat from 'dateformat';
import { debounceByAnimationFrame } from '~/lib/utils/common_utils'; import { debounceByAnimationFrame } from '~/lib/utils/common_utils';
import { getSvgIconPathContent } from '~/lib/utils/icon_utils'; import { getSvgIconPathContent } from '~/lib/utils/icon_utils';
import Icon from '~/vue_shared/components/icon.vue'; import Icon from '~/vue_shared/components/icon.vue';
import { chartHeight, graphTypes, lineTypes } from '../../constants';
   
let debouncedResize; let debouncedResize;
   
Loading
@@ -19,7 +20,6 @@ export default {
Loading
@@ -19,7 +20,6 @@ export default {
required: true, required: true,
validator(data) { validator(data) {
return ( return (
data.queries &&
Array.isArray(data.queries) && Array.isArray(data.queries) &&
data.queries.filter(query => { data.queries.filter(query => {
if (Array.isArray(query.result)) { if (Array.isArray(query.result)) {
Loading
@@ -51,21 +51,44 @@ export default {
Loading
@@ -51,21 +51,44 @@ export default {
return { return {
tooltip: { tooltip: {
title: '', title: '',
content: '', content: [],
isDeployment: false, isDeployment: false,
sha: '', sha: '',
}, },
width: 0, width: 0,
height: 0, height: chartHeight,
scatterSymbol: undefined, svgs: {},
primaryColor: null,
}; };
}, },
computed: { computed: {
chartData() { chartData() {
return this.graphData.queries.reduce((accumulator, query) => { return this.graphData.queries.map(query => {
accumulator[query.unit] = query.result.reduce((acc, res) => acc.concat(res.values), []); const { appearance } = query;
return accumulator; const lineType =
}, {}); appearance && appearance.line && appearance.line.type
? appearance.line.type
: lineTypes.default;
const lineColor = lineType === lineTypes.threshold ? this.primaryColor : undefined;
return {
name: this.formatLegendLabel(query),
data: this.concatenateResults(query.result),
lineStyle: {
type: lineType,
color: lineColor,
},
itemStyle: {
color: lineColor,
},
areaStyle: {
opacity:
appearance && appearance.area && typeof appearance.area.opacity === 'number'
? appearance.area.opacity
: undefined,
},
};
});
}, },
chartOptions() { chartOptions() {
return { return {
Loading
@@ -78,28 +101,25 @@ export default {
Loading
@@ -78,28 +101,25 @@ export default {
axisPointer: { axisPointer: {
snap: true, snap: true,
}, },
nameTextStyle: {
padding: [18, 0, 0, 0],
},
}, },
yAxis: { yAxis: {
name: this.yAxisLabel, name: this.yAxisLabel,
axisLabel: { axisLabel: {
formatter: value => value.toFixed(3), formatter: value => value.toFixed(3),
}, },
nameTextStyle: {
padding: [0, 0, 36, 0],
},
},
legend: {
formatter: this.xAxisLabel,
}, },
series: this.scatterSeries, series: this.scatterSeries,
dataZoom: this.dataZoomConfig,
}; };
}, },
dataZoomConfig() {
const handleIcon = this.svgs['scroll-handle'];
return handleIcon ? { handleIcon } : {};
},
earliestDatapoint() { earliestDatapoint() {
return Object.values(this.chartData).reduce((acc, data) => { return this.chartData.reduce((acc, series) => {
const [[timestamp]] = data.sort(([a], [b]) => { const [[timestamp]] = series.data.sort(([a], [b]) => {
if (a < b) { if (a < b) {
return -1; return -1;
} }
Loading
@@ -129,15 +149,15 @@ export default {
Loading
@@ -129,15 +149,15 @@ export default {
}, },
scatterSeries() { scatterSeries() {
return { return {
type: 'scatter', type: graphTypes.deploymentData,
data: this.recentDeployments.map(deployment => [deployment.createdAt, 0]), data: this.recentDeployments.map(deployment => [deployment.createdAt, 0]),
symbol: this.scatterSymbol, symbol: this.svgs.rocket,
symbolSize: 14, symbolSize: 14,
itemStyle: {
color: this.primaryColor,
},
}; };
}, },
xAxisLabel() {
return this.graphData.queries.map(query => query.label).join(', ');
},
yAxisLabel() { yAxisLabel() {
return `${this.graphData.y_label}`; return `${this.graphData.y_label}`;
}, },
Loading
@@ -151,35 +171,54 @@ export default {
Loading
@@ -151,35 +171,54 @@ export default {
created() { created() {
debouncedResize = debounceByAnimationFrame(this.onResize); debouncedResize = debounceByAnimationFrame(this.onResize);
window.addEventListener('resize', debouncedResize); window.addEventListener('resize', debouncedResize);
this.getScatterSymbol(); this.setSvg('rocket');
this.setSvg('scroll-handle');
}, },
methods: { methods: {
concatenateResults(results) {
return results.reduce((acc, result) => acc.concat(result.values), []);
},
formatLegendLabel(query) {
return `${query.label}`;
},
formatTooltipText(params) { formatTooltipText(params) {
const [seriesData] = params.seriesData;
this.tooltip.isDeployment = seriesData.componentSubType === 'scatter';
this.tooltip.title = dateFormat(params.value, 'dd mmm yyyy, h:MMTT'); this.tooltip.title = dateFormat(params.value, 'dd mmm yyyy, h:MMTT');
if (this.tooltip.isDeployment) { this.tooltip.content = [];
const [deploy] = this.recentDeployments.filter( params.seriesData.forEach(seriesData => {
deployment => deployment.createdAt === seriesData.value[0], if (seriesData.componentSubType === graphTypes.deploymentData) {
); this.tooltip.isDeployment = true;
this.tooltip.sha = deploy.sha.substring(0, 8); const [deploy] = this.recentDeployments.filter(
} else { deployment => deployment.createdAt === seriesData.value[0],
this.tooltip.content = `${this.yAxisLabel} ${seriesData.value[1].toFixed(3)}`; );
} this.tooltip.sha = deploy.sha.substring(0, 8);
} else {
const { seriesName } = seriesData;
// seriesData.value contains the chart's [x, y] value pair
// seriesData.value[1] is threfore the chart y value
const value = seriesData.value[1].toFixed(3);
this.tooltip.content.push({
name: seriesName,
value,
});
}
});
}, },
getScatterSymbol() { setSvg(name) {
getSvgIconPathContent('rocket') getSvgIconPathContent(name)
.then(path => { .then(path => {
if (path) { if (path) {
this.scatterSymbol = `path://${path}`; this.$set(this.svgs, name, `path://${path}`);
} }
}) })
.catch(() => {}); .catch(() => {});
}, },
onChartUpdated(chart) {
[this.primaryColor] = chart.getOption().color;
},
onResize() { onResize() {
const { width, height } = this.$refs.areaChart.$el.getBoundingClientRect(); const { width } = this.$refs.areaChart.$el.getBoundingClientRect();
this.width = width; this.width = width;
this.height = height;
}, },
}, },
}; };
Loading
@@ -200,6 +239,7 @@ export default {
Loading
@@ -200,6 +239,7 @@ export default {
:thresholds="alertData" :thresholds="alertData"
:width="width" :width="width"
:height="height" :height="height"
@updated="onChartUpdated"
> >
<template slot="tooltipTitle"> <template slot="tooltipTitle">
<div v-if="tooltip.isDeployment"> <div v-if="tooltip.isDeployment">
Loading
@@ -213,7 +253,13 @@ export default {
Loading
@@ -213,7 +253,13 @@ export default {
{{ tooltip.sha }} {{ tooltip.sha }}
</div> </div>
<template v-else> <template v-else>
{{ tooltip.content }} <div
v-for="(content, key) in tooltip.content"
:key="key"
class="d-flex justify-content-between"
>
{{ content.name }} {{ content.value }}
</div>
</template> </template>
</template> </template>
</gl-area-chart> </gl-area-chart>
Loading
Loading
export const chartHeight = 300;
export const graphTypes = {
deploymentData: 'scatter',
};
export const lineTypes = {
default: 'solid',
threshold: 'dashed',
};
Loading
@@ -193,6 +193,10 @@ export default {
Loading
@@ -193,6 +193,10 @@ export default {
const noteObj = utils.findNoteObjectById(state.discussions, note.discussion_id); const noteObj = utils.findNoteObjectById(state.discussions, note.discussion_id);
   
if (noteObj.individual_note) { if (noteObj.individual_note) {
if (note.type === constants.DISCUSSION_NOTE) {
noteObj.individual_note = false;
}
noteObj.notes.splice(0, 1, note); noteObj.notes.splice(0, 1, note);
} else { } else {
const comment = utils.findNoteObjectById(noteObj.notes, note.id); const comment = utils.findNoteObjectById(noteObj.notes, note.id);
Loading
Loading
import projectSelect from '~/project_select'; import projectSelect from '~/project_select';
import initFilteredSearch from '~/pages/search/init_filtered_search'; import initFilteredSearch from '~/pages/search/init_filtered_search';
import addExtraTokensForMergeRequests from 'ee_else_ce/filtered_search/add_extra_tokens_for_merge_requests';
import IssuableFilteredSearchTokenKeys from '~/filtered_search/issuable_filtered_search_token_keys'; import IssuableFilteredSearchTokenKeys from '~/filtered_search/issuable_filtered_search_token_keys';
import { FILTERED_SEARCH } from '~/pages/constants'; import { FILTERED_SEARCH } from '~/pages/constants';
   
document.addEventListener('DOMContentLoaded', () => { document.addEventListener('DOMContentLoaded', () => {
IssuableFilteredSearchTokenKeys.addExtraTokensForMergeRequests(); addExtraTokensForMergeRequests(IssuableFilteredSearchTokenKeys);
   
initFilteredSearch({ initFilteredSearch({
page: FILTERED_SEARCH.MERGE_REQUESTS, page: FILTERED_SEARCH.MERGE_REQUESTS,
Loading
Loading
Loading
@@ -2,6 +2,5 @@ import PersistentUserCallout from '~/persistent_user_callout';
Loading
@@ -2,6 +2,5 @@ import PersistentUserCallout from '~/persistent_user_callout';
   
document.addEventListener('DOMContentLoaded', () => { document.addEventListener('DOMContentLoaded', () => {
const callout = document.querySelector('.gcp-signup-offer'); const callout = document.querySelector('.gcp-signup-offer');
PersistentUserCallout.factory(callout);
if (callout) new PersistentUserCallout(callout); // eslint-disable-line no-new
}); });
Loading
@@ -3,8 +3,7 @@ import initGkeDropdowns from '~/projects/gke_cluster_dropdowns';
Loading
@@ -3,8 +3,7 @@ import initGkeDropdowns from '~/projects/gke_cluster_dropdowns';
   
function initGcpSignupCallout() { function initGcpSignupCallout() {
const callout = document.querySelector('.gcp-signup-offer'); const callout = document.querySelector('.gcp-signup-offer');
PersistentUserCallout.factory(callout);
if (callout) new PersistentUserCallout(callout); // eslint-disable-line no-new
} }
   
document.addEventListener('DOMContentLoaded', () => { document.addEventListener('DOMContentLoaded', () => {
Loading
Loading
import projectSelect from '~/project_select'; import projectSelect from '~/project_select';
import initFilteredSearch from '~/pages/search/init_filtered_search'; import initFilteredSearch from '~/pages/search/init_filtered_search';
import IssuableFilteredSearchTokenKeys from '~/filtered_search/issuable_filtered_search_token_keys'; import IssuableFilteredSearchTokenKeys from '~/filtered_search/issuable_filtered_search_token_keys';
import addExtraTokensForMergeRequests from 'ee_else_ce/filtered_search/add_extra_tokens_for_merge_requests';
import { FILTERED_SEARCH } from '~/pages/constants'; import { FILTERED_SEARCH } from '~/pages/constants';
   
document.addEventListener('DOMContentLoaded', () => { document.addEventListener('DOMContentLoaded', () => {
IssuableFilteredSearchTokenKeys.addExtraTokensForMergeRequests(); addExtraTokensForMergeRequests(IssuableFilteredSearchTokenKeys);
   
initFilteredSearch({ initFilteredSearch({
page: FILTERED_SEARCH.MERGE_REQUESTS, page: FILTERED_SEARCH.MERGE_REQUESTS,
Loading
Loading
Loading
@@ -56,30 +56,34 @@ document.addEventListener('DOMContentLoaded', () => {
Loading
@@ -56,30 +56,34 @@ document.addEventListener('DOMContentLoaded', () => {
   
import(/* webpackChunkName: 'emoji' */ '~/emoji') import(/* webpackChunkName: 'emoji' */ '~/emoji')
.then(Emoji => { .then(Emoji => {
const emojiMenu = new EmojiMenu( Emoji.initEmojiMap()
Emoji, .then(() => {
toggleEmojiMenuButtonSelector, const emojiMenu = new EmojiMenu(
'js-status-emoji-menu', Emoji,
selectEmojiCallback, toggleEmojiMenuButtonSelector,
); 'js-status-emoji-menu',
emojiMenu.bindEvents(); selectEmojiCallback,
);
emojiMenu.bindEvents();
   
const defaultEmojiTag = Emoji.glEmojiTag(defaultStatusEmoji); const defaultEmojiTag = Emoji.glEmojiTag(defaultStatusEmoji);
statusMessageField.addEventListener('input', () => { statusMessageField.addEventListener('input', () => {
const hasStatusMessage = statusMessageField.value.trim() !== ''; const hasStatusMessage = statusMessageField.value.trim() !== '';
const statusEmoji = findStatusEmoji(); const statusEmoji = findStatusEmoji();
if (hasStatusMessage && statusEmoji) { if (hasStatusMessage && statusEmoji) {
return; return;
} }
   
if (hasStatusMessage) { if (hasStatusMessage) {
toggleNoEmojiPlaceholder(false); toggleNoEmojiPlaceholder(false);
toggleEmojiMenuButton.innerHTML += defaultEmojiTag; toggleEmojiMenuButton.innerHTML += defaultEmojiTag;
} else if (statusEmoji.dataset.name === defaultStatusEmoji) { } else if (statusEmoji.dataset.name === defaultStatusEmoji) {
toggleNoEmojiPlaceholder(true); toggleNoEmojiPlaceholder(true);
removeStatusEmoji(); removeStatusEmoji();
} }
}); });
})
.catch(() => createFlash('Failed to load emoji list.'));
}) })
.catch(() => createFlash('Failed to load emoji list.')); .catch(() => createFlash('Failed to load emoji list.'));
}); });
Loading
@@ -2,6 +2,5 @@ import PersistentUserCallout from '~/persistent_user_callout';
Loading
@@ -2,6 +2,5 @@ import PersistentUserCallout from '~/persistent_user_callout';
   
document.addEventListener('DOMContentLoaded', () => { document.addEventListener('DOMContentLoaded', () => {
const callout = document.querySelector('.gcp-signup-offer'); const callout = document.querySelector('.gcp-signup-offer');
PersistentUserCallout.factory(callout);
if (callout) new PersistentUserCallout(callout); // eslint-disable-line no-new
}); });
Loading
@@ -13,7 +13,7 @@ document.addEventListener('DOMContentLoaded', () => {
Loading
@@ -13,7 +13,7 @@ document.addEventListener('DOMContentLoaded', () => {
   
if (newClusterViews.indexOf(page) > -1) { if (newClusterViews.indexOf(page) > -1) {
const callout = document.querySelector('.gcp-signup-offer'); const callout = document.querySelector('.gcp-signup-offer');
if (callout) new PersistentUserCallout(callout); // eslint-disable-line no-new PersistentUserCallout.factory(callout);
   
initGkeDropdowns(); initGkeDropdowns();
} }
Loading
Loading
Loading
@@ -2,12 +2,13 @@ import IssuableIndex from '~/issuable_index';
Loading
@@ -2,12 +2,13 @@ import IssuableIndex from '~/issuable_index';
import ShortcutsNavigation from '~/behaviors/shortcuts/shortcuts_navigation'; import ShortcutsNavigation from '~/behaviors/shortcuts/shortcuts_navigation';
import UsersSelect from '~/users_select'; import UsersSelect from '~/users_select';
import initFilteredSearch from '~/pages/search/init_filtered_search'; import initFilteredSearch from '~/pages/search/init_filtered_search';
import addExtraTokensForMergeRequests from 'ee_else_ce/filtered_search/add_extra_tokens_for_merge_requests';
import IssuableFilteredSearchTokenKeys from '~/filtered_search/issuable_filtered_search_token_keys'; import IssuableFilteredSearchTokenKeys from '~/filtered_search/issuable_filtered_search_token_keys';
import { FILTERED_SEARCH } from '~/pages/constants'; import { FILTERED_SEARCH } from '~/pages/constants';
import { ISSUABLE_INDEX } from '~/pages/projects/constants'; import { ISSUABLE_INDEX } from '~/pages/projects/constants';
   
document.addEventListener('DOMContentLoaded', () => { document.addEventListener('DOMContentLoaded', () => {
IssuableFilteredSearchTokenKeys.addExtraTokensForMergeRequests(); addExtraTokensForMergeRequests(IssuableFilteredSearchTokenKeys);
   
initFilteredSearch({ initFilteredSearch({
page: FILTERED_SEARCH.MERGE_REQUESTS, page: FILTERED_SEARCH.MERGE_REQUESTS,
Loading
Loading
Loading
@@ -10,6 +10,12 @@ import { __ } from '~/locale';
Loading
@@ -10,6 +10,12 @@ import { __ } from '~/locale';
   
const d3 = { select, scaleLinear, scaleThreshold }; const d3 = { select, scaleLinear, scaleThreshold };
   
const firstDayOfWeekChoices = Object.freeze({
sunday: 0,
monday: 1,
saturday: 6,
});
const LOADING_HTML = ` const LOADING_HTML = `
<div class="text-center"> <div class="text-center">
<i class="fa fa-spinner fa-spin user-calendar-activities-loading"></i> <i class="fa fa-spinner fa-spin user-calendar-activities-loading"></i>
Loading
@@ -49,7 +55,7 @@ export default class ActivityCalendar {
Loading
@@ -49,7 +55,7 @@ export default class ActivityCalendar {
timestamps, timestamps,
calendarActivitiesPath, calendarActivitiesPath,
utcOffset = 0, utcOffset = 0,
firstDayOfWeek = 0, firstDayOfWeek = firstDayOfWeekChoices.sunday,
monthsAgo = 12, monthsAgo = 12,
) { ) {
this.calendarActivitiesPath = calendarActivitiesPath; this.calendarActivitiesPath = calendarActivitiesPath;
Loading
@@ -206,11 +212,16 @@ export default class ActivityCalendar {
Loading
@@ -206,11 +212,16 @@ export default class ActivityCalendar {
}, },
]; ];
   
if (this.firstDayOfWeek === 1) { if (this.firstDayOfWeek === firstDayOfWeekChoices.monday) {
days.push({ days.push({
text: 'S', text: 'S',
y: 29 + this.dayYPos(7), y: 29 + this.dayYPos(7),
}); });
} else if (this.firstDayOfWeek === firstDayOfWeekChoices.saturday) {
days.push({
text: 'S',
y: 29 + this.dayYPos(6),
});
} }
   
this.svg this.svg
Loading
Loading
Loading
@@ -31,4 +31,12 @@ export default class PersistentUserCallout {
Loading
@@ -31,4 +31,12 @@ export default class PersistentUserCallout {
Flash(__('An error occurred while dismissing the alert. Refresh the page and try again.')); Flash(__('An error occurred while dismissing the alert. Refresh the page and try again.'));
}); });
} }
static factory(container) {
if (!container) {
return undefined;
}
return new PersistentUserCallout(container);
}
} }
<script>
import _ from 'underscore';
import GlModal from '~/vue_shared/components/gl_modal.vue';
import { GlLink } from '@gitlab/ui';
import ClipboardButton from '~/vue_shared/components/clipboard_button.vue';
import CiIcon from '~/vue_shared/components/ci_icon.vue';
import { s__, sprintf } from '~/locale';
/**
* Pipeline Stop Modal.
*
* Renders the modal used to confirm stopping a pipeline.
*/
export default {
components: {
GlModal,
GlLink,
ClipboardButton,
CiIcon,
},
props: {
pipeline: {
type: Object,
required: true,
deep: true,
},
},
computed: {
modalTitle() {
return sprintf(
s__('Pipeline|Stop pipeline #%{pipelineId}?'),
{
pipelineId: `${this.pipeline.id}`,
},
false,
);
},
modalText() {
return sprintf(
s__(`Pipeline|You’re about to stop pipeline %{pipelineId}.`),
{
pipelineId: `<strong>#${this.pipeline.id}</strong>`,
},
false,
);
},
hasRef() {
return !_.isEmpty(this.pipeline.ref);
},
},
methods: {
emitSubmit(event) {
this.$emit('submit', event);
},
},
};
</script>
<template>
<gl-modal
id="confirmation-modal"
:header-title-text="modalTitle"
:footer-primary-button-text="s__('Pipeline|Stop pipeline')"
footer-primary-button-variant="danger"
@submit="emitSubmit($event)"
>
<p v-html="modalText"></p>
<p v-if="pipeline">
<ci-icon
v-if="pipeline.details"
:status="pipeline.details.status"
class="vertical-align-middle"
/>
<span class="font-weight-bold">{{ __('Pipeline') }}</span>
<a :href="pipeline.path" class="js-pipeline-path link-commit qa-pipeline-path"
>#{{ pipeline.id }}</a
>
<template v-if="hasRef">
{{ __('from') }}
<a :href="pipeline.ref.path" class="link-commit ref-name">{{ pipeline.ref.name }}</a>
</template>
</p>
<template v-if="pipeline.commit">
<p>
<span class="font-weight-bold">{{ __('Commit') }}</span>
<gl-link :href="pipeline.commit.commit_path" class="js-commit-sha commit-sha link-commit">
{{ pipeline.commit.short_id }}
</gl-link>
</p>
<p>{{ pipeline.commit.title }}</p>
</template>
</gl-modal>
</template>
<script> <script>
import Modal from '~/vue_shared/components/gl_modal.vue';
import { s__, sprintf } from '~/locale';
import PipelinesTableRowComponent from './pipelines_table_row.vue'; import PipelinesTableRowComponent from './pipelines_table_row.vue';
import PipelineStopModal from './pipeline_stop_modal.vue';
import eventHub from '../event_hub'; import eventHub from '../event_hub';
   
/** /**
Loading
@@ -12,7 +11,7 @@ import eventHub from '../event_hub';
Loading
@@ -12,7 +11,7 @@ import eventHub from '../event_hub';
export default { export default {
components: { components: {
PipelinesTableRowComponent, PipelinesTableRowComponent,
Modal, PipelineStopModal,
}, },
props: { props: {
pipelines: { pipelines: {
Loading
@@ -36,30 +35,11 @@ export default {
Loading
@@ -36,30 +35,11 @@ export default {
data() { data() {
return { return {
pipelineId: 0, pipelineId: 0,
pipeline: {},
endpoint: '', endpoint: '',
cancelingPipeline: null, cancelingPipeline: null,
}; };
}, },
computed: {
modalTitle() {
return sprintf(
s__('Pipeline|Stop pipeline #%{pipelineId}?'),
{
pipelineId: `${this.pipelineId}`,
},
false,
);
},
modalText() {
return sprintf(
s__('Pipeline|You’re about to stop pipeline %{pipelineId}.'),
{
pipelineId: `<strong>#${this.pipelineId}</strong>`,
},
false,
);
},
},
created() { created() {
eventHub.$on('openConfirmationModal', this.setModalData); eventHub.$on('openConfirmationModal', this.setModalData);
}, },
Loading
@@ -68,7 +48,8 @@ export default {
Loading
@@ -68,7 +48,8 @@ export default {
}, },
methods: { methods: {
setModalData(data) { setModalData(data) {
this.pipelineId = data.pipelineId; this.pipelineId = data.pipeline.id;
this.pipeline = data.pipeline;
this.endpoint = data.endpoint; this.endpoint = data.endpoint;
}, },
onSubmit() { onSubmit() {
Loading
@@ -103,15 +84,6 @@ export default {
Loading
@@ -103,15 +84,6 @@ export default {
:view-type="viewType" :view-type="viewType"
:canceling-pipeline="cancelingPipeline" :canceling-pipeline="cancelingPipeline"
/> />
<pipeline-stop-modal :pipeline="pipeline" @submit="onSubmit" />
<modal
id="confirmation-modal"
:header-title-text="modalTitle"
:footer-primary-button-text="s__('Pipeline|Stop pipeline')"
footer-primary-button-variant="danger"
@submit="onSubmit"
>
<span v-html="modalText"></span>
</modal>
</div> </div>
</template> </template>
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