Commit 1dfecf3e authored by Fatih Acet's avatar Fatih Acet

Merge branch 'prettify-all-the-things-6' into 'master'

Prettify all the things (part 6)

See merge request gitlab-org/gitlab-ce!22256
parents 3e3f8ac8 3271c5f0
...@@ -22,9 +22,7 @@ export default { ...@@ -22,9 +22,7 @@ export default {
directives: { directives: {
tooltip, tooltip,
}, },
mixins: [ mixins: [timeagoMixin],
timeagoMixin,
],
props: { props: {
deployment: { deployment: {
type: Object, type: Object,
...@@ -50,7 +48,7 @@ export default { ...@@ -50,7 +48,7 @@ export default {
return !!(this.deployment.url && this.deployment.name); return !!(this.deployment.url && this.deployment.name);
}, },
hasMetrics() { hasMetrics() {
return !!(this.deployment.metrics_url); return !!this.deployment.metrics_url;
}, },
}, },
methods: { methods: {
...@@ -63,7 +61,7 @@ export default { ...@@ -63,7 +61,7 @@ export default {
MRWidgetService.stopEnvironment(this.deployment.stop_url) MRWidgetService.stopEnvironment(this.deployment.stop_url)
.then(res => res.data) .then(res => res.data)
.then((data) => { .then(data => {
if (data.redirect_url) { if (data.redirect_url) {
visitUrl(data.redirect_url); visitUrl(data.redirect_url);
} }
......
...@@ -60,11 +60,29 @@ export default { ...@@ -60,11 +60,29 @@ export default {
let memoryUsageMsg = ''; let memoryUsageMsg = '';
if (memoryTo > memoryFrom) { if (memoryTo > memoryFrom) {
memoryUsageMsg = sprintf(s__('mrWidget|%{metricsLinkStart} Memory %{metricsLinkEnd} usage %{emphasisStart} increased %{emphasisEnd} from %{memoryFrom}MB to %{memoryTo}MB'), messageProps, false); memoryUsageMsg = sprintf(
s__(
'mrWidget|%{metricsLinkStart} Memory %{metricsLinkEnd} usage %{emphasisStart} increased %{emphasisEnd} from %{memoryFrom}MB to %{memoryTo}MB',
),
messageProps,
false,
);
} else if (memoryTo < memoryFrom) { } else if (memoryTo < memoryFrom) {
memoryUsageMsg = sprintf(s__('mrWidget|%{metricsLinkStart} Memory %{metricsLinkEnd} usage %{emphasisStart} decreased %{emphasisEnd} from %{memoryFrom}MB to %{memoryTo}MB'), messageProps, false); memoryUsageMsg = sprintf(
s__(
'mrWidget|%{metricsLinkStart} Memory %{metricsLinkEnd} usage %{emphasisStart} decreased %{emphasisEnd} from %{memoryFrom}MB to %{memoryTo}MB',
),
messageProps,
false,
);
} else { } else {
memoryUsageMsg = sprintf(s__('mrWidget|%{metricsLinkStart} Memory %{metricsLinkEnd} usage is %{emphasisStart} unchanged %{emphasisEnd} at %{memoryFrom}MB'), messageProps, false); memoryUsageMsg = sprintf(
s__(
'mrWidget|%{metricsLinkStart} Memory %{metricsLinkEnd} usage is %{emphasisStart} unchanged %{emphasisEnd} at %{memoryFrom}MB',
),
messageProps,
false,
);
} }
return memoryUsageMsg; return memoryUsageMsg;
...@@ -77,7 +95,7 @@ export default { ...@@ -77,7 +95,7 @@ export default {
methods: { methods: {
getMegabytes(bytesString) { getMegabytes(bytesString) {
const valueInBytes = Number(bytesString).toFixed(2); const valueInBytes = Number(bytesString).toFixed(2);
return (bytesToMiB(valueInBytes)).toFixed(2); return bytesToMiB(valueInBytes).toFixed(2);
}, },
computeGraphData(metrics, deploymentTime) { computeGraphData(metrics, deploymentTime) {
this.loadingMetrics = false; this.loadingMetrics = false;
...@@ -103,7 +121,7 @@ export default { ...@@ -103,7 +121,7 @@ export default {
loadMetrics() { loadMetrics() {
backOff((next, stop) => { backOff((next, stop) => {
MRWidgetService.fetchMetrics(this.metricsUrl) MRWidgetService.fetchMetrics(this.metricsUrl)
.then((res) => { .then(res => {
if (res.status === statusCodes.NO_CONTENT) { if (res.status === statusCodes.NO_CONTENT) {
this.backOffRequestCounter += 1; this.backOffRequestCounter += 1;
/* eslint-disable no-unused-expressions */ /* eslint-disable no-unused-expressions */
...@@ -114,14 +132,14 @@ export default { ...@@ -114,14 +132,14 @@ export default {
}) })
.catch(stop); .catch(stop);
}) })
.then((res) => { .then(res => {
if (res.status === statusCodes.NO_CONTENT) { if (res.status === statusCodes.NO_CONTENT) {
return res; return res;
} }
return res.data; return res.data;
}) })
.then((data) => { .then(data => {
this.computeGraphData(data.metrics, data.deployment_time); this.computeGraphData(data.metrics, data.deployment_time);
return data; return data;
}) })
......
<script> <script>
import tooltip from '../../vue_shared/directives/tooltip'; import tooltip from '../../vue_shared/directives/tooltip';
export default { export default {
name: 'MrWidgetAuthor', name: 'MrWidgetAuthor',
directives: { directives: {
tooltip, tooltip,
},
props: {
author: {
type: Object,
required: true,
}, },
props: { showAuthorName: {
author: { type: Boolean,
type: Object, required: false,
required: true, default: true,
},
showAuthorName: {
type: Boolean,
required: false,
default: true,
},
showAuthorTooltip: {
type: Boolean,
required: false,
default: false,
},
}, },
computed: { showAuthorTooltip: {
authorUrl() { type: Boolean,
return this.author.webUrl || this.author.web_url; required: false,
}, default: false,
avatarUrl() {
return this.author.avatarUrl || this.author.avatar_url;
},
}, },
}; },
computed: {
authorUrl() {
return this.author.webUrl || this.author.web_url;
},
avatarUrl() {
return this.author.avatarUrl || this.author.avatar_url;
},
},
};
</script> </script>
<template> <template>
<a <a
......
<script> <script>
import tooltip from '~/vue_shared/directives/tooltip'; import tooltip from '~/vue_shared/directives/tooltip';
import MrWidgetAuthor from './mr_widget_author.vue'; import MrWidgetAuthor from './mr_widget_author.vue';
export default { export default {
name: 'MrWidgetAuthorTime', name: 'MrWidgetAuthorTime',
components: { components: {
MrWidgetAuthor, MrWidgetAuthor,
},
directives: {
tooltip,
},
props: {
actionText: {
type: String,
required: true,
}, },
directives: { author: {
tooltip, type: Object,
required: true,
}, },
props: { dateTitle: {
actionText: { type: String,
type: String, required: true,
required: true,
},
author: {
type: Object,
required: true,
},
dateTitle: {
type: String,
required: true,
},
dateReadable: {
type: String,
required: true,
},
}, },
}; dateReadable: {
type: String,
required: true,
},
},
};
</script> </script>
<template> <template>
<h4 class="js-mr-widget-author"> <h4 class="js-mr-widget-author">
......
<script> <script>
import { sprintf, s__ } from '~/locale'; import { sprintf, s__ } from '~/locale';
export default { export default {
name: 'MRWidgetMergeHelp', name: 'MRWidgetMergeHelp',
props: { props: {
missingBranch: { missingBranch: {
type: String, type: String,
required: false, required: false,
default: '', default: '',
},
}, },
computed: { },
missingBranchInfo() { computed: {
return sprintf( missingBranchInfo() {
s__('mrWidget|If the %{branch} branch exists in your local repository, you can merge this merge request manually using the'), return sprintf(
{ branch: this.missingBranch }, s__(
); 'mrWidget|If the %{branch} branch exists in your local repository, you can merge this merge request manually using the',
}, ),
{ branch: this.missingBranch },
);
}, },
}; },
};
</script> </script>
<template> <template>
<section class="mr-widget-help"> <section class="mr-widget-help">
......
<script> <script>
import { s__ } from '~/locale'; import { s__ } from '~/locale';
export default { export default {
name: 'MRWidgetRelatedLinks', name: 'MRWidgetRelatedLinks',
props: { props: {
relatedLinks: { relatedLinks: {
type: Object, type: Object,
required: true, required: true,
default: () => ({}), default: () => ({}),
},
state: {
type: String,
required: false,
default: '',
},
}, },
computed: { state: {
closesText() { type: String,
if (this.state === 'merged') { required: false,
return s__('mrWidget|Closed'); default: '',
}
if (this.state === 'closed') {
return s__('mrWidget|Did not close');
}
return s__('mrWidget|Closes');
},
}, },
}; },
computed: {
closesText() {
if (this.state === 'merged') {
return s__('mrWidget|Closed');
}
if (this.state === 'closed') {
return s__('mrWidget|Did not close');
}
return s__('mrWidget|Closes');
},
},
};
</script> </script>
<template> <template>
<section class="mr-info-list mr-links"> <section class="mr-info-list mr-links">
......
<script> <script>
import ciIcon from '../../vue_shared/components/ci_icon.vue'; import ciIcon from '../../vue_shared/components/ci_icon.vue';
export default { export default {
components: { components: {
ciIcon, ciIcon,
},
props: {
status: {
type: String,
required: true,
}, },
props: { showDisabledButton: {
status: { type: Boolean,
type: String, required: false,
required: true, default: false,
},
showDisabledButton: {
type: Boolean,
required: false,
default: false,
},
}, },
computed: { },
isLoading() { computed: {
return this.status === 'loading'; isLoading() {
}, return this.status === 'loading';
statusObj() {
return {
group: this.status,
icon: `status_${this.status}`,
};
},
}, },
}; statusObj() {
return {
group: this.status,
icon: `status_${this.status}`,
};
},
},
};
</script> </script>
<template> <template>
<div class="space-children d-flex append-right-10 widget-status-icon"> <div class="space-children d-flex append-right-10 widget-status-icon">
......
<script> <script>
import tooltip from '../../vue_shared/directives/tooltip'; import tooltip from '../../vue_shared/directives/tooltip';
import { __ } from '../../locale'; import { __ } from '../../locale';
export default { export default {
directives: { directives: {
tooltip, tooltip,
}, },
created() { created() {
this.removesBranchText = __('<strong>Removes</strong> source branch'); this.removesBranchText = __('<strong>Removes</strong> source branch');
this.tooltipTitle = __('A user with write access to the source branch selected this option'); this.tooltipTitle = __('A user with write access to the source branch selected this option');
}, },
}; };
</script> </script>
<template> <template>
......
<script> <script>
import statusIcon from '../mr_widget_status_icon.vue'; import statusIcon from '../mr_widget_status_icon.vue';
export default { export default {
name: 'MRWidgetArchived', name: 'MRWidgetArchived',
components: { components: {
statusIcon, statusIcon,
}, },
}; };
</script> </script>
<template> <template>
<div class="mr-widget-body media"> <div class="mr-widget-body media">
......
<script> <script>
import eventHub from '../../event_hub'; import eventHub from '../../event_hub';
import statusIcon from '../mr_widget_status_icon.vue'; import statusIcon from '../mr_widget_status_icon.vue';
export default { export default {
name: 'MRWidgetAutoMergeFailed', name: 'MRWidgetAutoMergeFailed',
components: { components: {
statusIcon, statusIcon,
},
props: {
mr: {
type: Object,
required: true,
}, },
props: { },
mr: { data() {
type: Object, return {
required: true, isRefreshing: false,
}, };
},
methods: {
refreshWidget() {
this.isRefreshing = true;
eventHub.$emit('MRWidgetUpdateRequested', () => {
this.isRefreshing = false;
});
}, },
data() { },
return { };
isRefreshing: false,
};
},
methods: {
refreshWidget() {
this.isRefreshing = true;
eventHub.$emit('MRWidgetUpdateRequested', () => {
this.isRefreshing = false;
});
},
},
};
</script> </script>
<template> <template>
<div class="mr-widget-body media"> <div class="mr-widget-body media">
......
<script> <script>
import statusIcon from '../mr_widget_status_icon.vue'; import statusIcon from '../mr_widget_status_icon.vue';
export default { export default {
name: 'MRWidgetChecking', name: 'MRWidgetChecking',
components: { components: {
statusIcon, statusIcon,
}, },
}; };
</script> </script>
<template> <template>
<div class="mr-widget-body media"> <div class="mr-widget-body media">
......
<script> <script>
import MrWidgetAuthorTime from '../../components/mr_widget_author_time.vue'; import MrWidgetAuthorTime from '../../components/mr_widget_author_time.vue';
import statusIcon from '../mr_widget_status_icon.vue'; import statusIcon from '../mr_widget_status_icon.vue';
export default { export default {
name: 'MRWidgetClosed', name: 'MRWidgetClosed',
components: { components: {
MrWidgetAuthorTime, MrWidgetAuthorTime,
statusIcon, statusIcon,
}, },
props: { props: {
/* TODO: This is providing all store and service down when it /* TODO: This is providing all store and service down when it
only needs metrics and targetBranch */ only needs metrics and targetBranch */
mr: { mr: {
type: Object, type: Object,
required: true, required: true,
default: () => ({}), default: () => ({}),
},
}, },
}; },
};
</script> </script>
<template> <template>
<div class="mr-widget-body media"> <div class="mr-widget-body media">
......
<script> <script>
import statusIcon from '../mr_widget_status_icon.vue'; import statusIcon from '../mr_widget_status_icon.vue';
export default { export default {
name: 'MRWidgetConflicts', name: 'MRWidgetConflicts',
components: { components: {
statusIcon, statusIcon,
}, },
props: { props: {
/* TODO: This is providing all store and service down when it /* TODO: This is providing all store and service down when it
only needs a few props */ only needs a few props */
mr: { mr: {
type: Object, type: Object,
required: true, required: true,
default: () => ({}), default: () => ({}),
},
}, },
}; },
};
</script> </script>
<template> <template>
<div class="mr-widget-body media"> <div class="mr-widget-body media">
......
<script> <script>
import Flash from '../../../flash'; import Flash from '../../../flash';
import statusIcon from '../mr_widget_status_icon.vue'; import statusIcon from '../mr_widget_status_icon.vue';
import MrWidgetAuthor from '../../components/mr_widget_author.vue'; import MrWidgetAuthor from '../../components/mr_widget_author.vue';
import eventHub from '../../event_hub'; import eventHub from '../../event_hub';
export default { export default {
name: 'MRWidgetMergeWhenPipelineSucceeds', name: 'MRWidgetMergeWhenPipelineSucceeds',
components: { components: {
MrWidgetAuthor, MrWidgetAuthor,
statusIcon, statusIcon,
},
props: {
mr: {
type: Object,
required: true,
default: () => ({}),
}, },
props: { service: {
mr: { type: Object,
type: Object, required: true,
required: true, default: () => ({}),
default: () => ({}),
},
service: {
type: Object,
required: true,
default: () => ({}),
},
}, },
data() { },
return { data() {
isCancellingAutoMerge: false, return {
isRemovingSourceBranch: false, isCancellingAutoMerge: false,
}; isRemovingSourceBranch: false,
}, };
computed: { },
canRemoveSourceBranch() { computed: {
const { canRemoveSourceBranch() {
shouldRemoveSourceBranch, const {
canRemoveSourceBranch, shouldRemoveSourceBranch,
mergeUserId, canRemoveSourceBranch,
currentUserId, mergeUserId,
} = this.mr; currentUserId,
} = this.mr;
return !shouldRemoveSourceBranch && return !shouldRemoveSourceBranch && canRemoveSourceBranch && mergeUserId === currentUserId;
canRemoveSourceBranch &&
mergeUserId === currentUserId;
},
}, },
methods: { },
cancelAutomaticMerge() { methods: {
this.isCancellingAutoMerge = true; cancelAutomaticMerge() {
this.service.cancelAutomaticMerge() this.isCancellingAutoMerge = true;
.then(res => res.data) this.service
.then((data) => { .cancelAutomaticMerge()
eventHub.$emit('UpdateWidgetData', data); .then(res => res.data)
}) .then(data => {
.catch(() => { eventHub.$emit('UpdateWidgetData', data);
this.isCancellingAutoMerge = false; })
Flash('Something went wrong. Please try again.'); .catch(() => {
}); this.isCancellingAutoMerge = false;
}, Flash('Something went wrong. Please try again.');
removeSourceBranch() { });
const options = { },
sha: this.mr.sha, removeSourceBranch() {
merge_when_pipeline_succeeds: true, const options = {
should_remove_source_branch: true, sha: this.mr.sha,
}; merge_when_pipeline_succeeds: true,
should_remove_source_branch: true,
};
this.isRemovingSourceBranch = true; this.isRemovingSourceBranch = true;
this.service.merge(options) this.service
.then(res => res.data) .merge(options)
.then((data) => { .then(res => res.data)
if (data.status === 'merge_when_pipeline_succeeds') { .then(data => {
eventHub.$emit('MRWidgetUpdateRequested'); if (data.status === 'merge_when_pipeline_succeeds') {
} eventHub.$emit('MRWidgetUpdateRequested');
}) }
.catch(() => { })
this.isRemovingSourceBranch = false; .catch(() => {
Flash('Something went wrong. Please try again.'); this.isRemovingSourceBranch = false;
}); Flash('Something went wrong. Please try again.');
}, });
}, },
}; },
};
</script> </script>
<template> <template>
<div class="mr-widget-body media"> <div class="mr-widget-body media">
......
<script> <script>
import Flash from '~/flash'; import Flash from '~/flash';
import tooltip from '~/vue_shared/directives/tooltip'; import tooltip from '~/vue_shared/directives/tooltip';
import { s__, __ } from '~/locale'; import { s__, __ } from '~/locale';
import ClipboardButton from '~/vue_shared/components/clipboard_button.vue'; import ClipboardButton from '~/vue_shared/components/clipboard_button.vue';
import MrWidgetAuthorTime from '../../components/mr_widget_author_time.vue'; import MrWidgetAuthorTime from '../../components/mr_widget_author_time.vue';
import statusIcon from '../mr_widget_status_icon.vue'; import statusIcon from '../mr_widget_status_icon.vue';
import eventHub from '../../event_hub'; import eventHub from '../../event_hub';
export default { export default {
name: 'MRWidgetMerged', name: 'MRWidgetMerged',
directives: { directives: {
tooltip, tooltip,
},
components: {
MrWidgetAuthorTime,
statusIcon,
ClipboardButton,
},
props: {
mr: {
type: Object,
required: true,
default: () => ({}),
}, },
components: { service: {
MrWidgetAuthorTime, type: Object,
statusIcon, required: true,
ClipboardButton, default: () => ({}),
}, },
props: { },
mr: { data() {
type: Object, return {
required: true, isMakingRequest: false,
default: () => ({}), };
}, },
service: { computed: {
type: Object, shouldShowRemoveSourceBranch() {
required: true, const { sourceBranchRemoved, isRemovingSourceBranch, canRemoveSourceBranch } = this.mr;
default: () => ({}),
}, return (
!sourceBranchRemoved &&
canRemoveSourceBranch &&
!this.isMakingRequest &&
!isRemovingSourceBranch
);
}, },
data() { shouldShowSourceBranchRemoving() {
return { const { sourceBranchRemoved, isRemovingSourceBranch } = this.mr;
isMakingRequest: false, return !sourceBranchRemoved && (isRemovingSourceBranch || this.isMakingRequest);
};
}, },
computed: { shouldShowMergedButtons() {
shouldShowRemoveSourceBranch() { const {
const { canRevertInCurrentMR,
sourceBranchRemoved, canCherryPickInCurrentMR,
isRemovingSourceBranch, revertInForkPath,
canRemoveSourceBranch, cherryPickInForkPath,
} = this.mr; } = this.mr;
return !sourceBranchRemoved &&
canRemoveSourceBranch &&
!this.isMakingRequest &&
!isRemovingSourceBranch;
},
shouldShowSourceBranchRemoving() {
const {
sourceBranchRemoved,
isRemovingSourceBranch,
} = this.mr;
return !sourceBranchRemoved &&
(isRemovingSourceBranch || this.isMakingRequest);
},
shouldShowMergedButtons() {
const {
canRevertInCurrentMR,
canCherryPickInCurrentMR,
revertInForkPath,
cherryPickInForkPath,
} = this.mr;
return canRevertInCurrentMR || return (
canCherryPickInCurrentMR || canRevertInCurrentMR || canCherryPickInCurrentMR || revertInForkPath || cherryPickInForkPath
revertInForkPath || );
cherryPickInForkPath; },
}, revertTitle() {
revertTitle() { return s__('mrWidget|Revert this merge request in a new merge request');
return s__('mrWidget|Revert this merge request in a new merge request'); },
}, cherryPickTitle() {
cherryPickTitle() { return s__('mrWidget|Cherry-pick this merge request in a new merge request');
return s__('mrWidget|Cherry-pick this merge request in a new merge request'); },
}, revertLabel() {
revertLabel() { return s__('mrWidget|Revert');
return s__('mrWidget|Revert'); },
}, cherryPickLabel() {
cherryPickLabel() { return s__('mrWidget|Cherry-pick');
return s__('mrWidget|Cherry-pick');
},
}, },
methods: { },
removeSourceBranch() { methods: {
this.isMakingRequest = true; removeSourceBranch() {
this.isMakingRequest = true;
this.service.removeSourceBranch() this.service
.then(res => res.data) .removeSourceBranch()
.then((data) => { .then(res => res.data)
if (data.message === 'Branch was removed') { .then(data => {
eventHub.$emit('MRWidgetUpdateRequested', () => { if (data.message === 'Branch was removed') {
this.isMakingRequest = false; eventHub.$emit('MRWidgetUpdateRequested', () => {
}); this.isMakingRequest = false;
} });
}) }
.catch(() => { })
this.isMakingRequest = false; .catch(() => {
Flash(__('Something went wrong. Please try again.')); this.isMakingRequest = false;
}); Flash(__('Something went wrong. Please try again.'));
}, });
}, },
}; },
};
</script> </script>
<template> <template>
<div class="mr-widget-body media"> <div class="mr-widget-body media">
......
<script> <script>
import statusIcon from '../mr_widget_status_icon.vue'; import statusIcon from '../mr_widget_status_icon.vue';
export default { export default {
name: 'MRWidgetMerging', name: 'MRWidgetMerging',
components: { components: {
statusIcon, statusIcon,
},
props: {
mr: {
type: Object,
required: true,
default: () => ({}),
}, },
props: { },
mr: { };
type: Object,
required: true,
default: () => ({}),
},
},
};
</script> </script>
<template> <template>
<div class="mr-widget-body mr-state-locked media"> <div class="mr-widget-body mr-state-locked media">
......
<script> <script>
import { sprintf, s__ } from '~/locale'; import { sprintf, s__ } from '~/locale';
import tooltip from '~/vue_shared/directives/tooltip'; import tooltip from '~/vue_shared/directives/tooltip';
import statusIcon from '../mr_widget_status_icon.vue'; import statusIcon from '../mr_widget_status_icon.vue';
import mrWidgetMergeHelp from '../../components/mr_widget_merge_help.vue'; import mrWidgetMergeHelp from '../../components/mr_widget_merge_help.vue';
export default { export default {
name: 'MRWidgetMissingBranch', name: 'MRWidgetMissingBranch',
directives: { directives: {
tooltip, tooltip,
},
components: {
mrWidgetMergeHelp,
statusIcon,
},
props: {
mr: {
type: Object,
required: true,
}, },
components: { },
mrWidgetMergeHelp, computed: {
statusIcon, missingBranchName() {
return this.mr.sourceBranchRemoved ? 'source' : 'target';
}, },
props: { missingBranchNameMessage() {
mr: { return sprintf(
type: Object, s__('mrWidget| Please restore it or use a different %{missingBranchName} branch'),
required: true, {
},
},
computed: {
missingBranchName() {
return this.mr.sourceBranchRemoved ? 'source' : 'target';
},
missingBranchNameMessage() {
return sprintf(s__('mrWidget| Please restore it or use a different %{missingBranchName} branch'), {
missingBranchName: this.missingBranchName, missingBranchName: this.missingBranchName,
}); },
}, );
message() { },
return sprintf(s__('mrWidget|If the %{missingBranchName} branch exists in your local repository, you can merge this merge request manually using the command line'), { message() {
return sprintf(
s__(
'mrWidget|If the %{missingBranchName} branch exists in your local repository, you can merge this merge request manually using the command line',
),
{
missingBranchName: this.missingBranchName, missingBranchName: this.missingBranchName,
}); },
}, );
}, },
}; },
};
</script> </script>
<template> <template>
<div class="mr-widget-body media"> <div class="mr-widget-body media">
......
<script> <script>
import StatusIcon from '../mr_widget_status_icon.vue'; import StatusIcon from '../mr_widget_status_icon.vue';
export default { export default {
name: 'MRWidgetNotAllowed', name: 'MRWidgetNotAllowed',
components: { components: {
StatusIcon, StatusIcon,
}, },
}; };
</script> </script>
<template> <template>
......
<script> <script>
import StatusIcon from '../mr_widget_status_icon.vue'; import StatusIcon from '../mr_widget_status_icon.vue';
export default { export default {
name: 'MRWidgetPipelineBlocked', name: 'MRWidgetPipelineBlocked',
components: { components: {
StatusIcon, StatusIcon,
}, },
}; };
</script> </script>
<template> <template>
<div class="mr-widget-body media"> <div class="mr-widget-body media">
......
<script> <script>
import simplePoll from '../../../lib/utils/simple_poll'; import simplePoll from '../../../lib/utils/simple_poll';
import eventHub from '../../event_hub'; import eventHub from '../../event_hub';
import statusIcon from '../mr_widget_status_icon.vue'; import statusIcon from '../mr_widget_status_icon.vue';
import Flash from '../../../flash'; import Flash from '../../../flash';
export default { export default {
name: 'MRWidgetRebase', name: 'MRWidgetRebase',
components: { components: {
statusIcon, statusIcon,
},
props: {
mr: {
type: Object,
required: true,
}, },
props: { service: {
mr: { type: Object,
type: Object, required: true,
required: true,
},
service: {
type: Object,
required: true,
},
}, },
data() { },
return { data() {
isMakingRequest: false, return {
rebasingError: null, isMakingRequest: false,
}; rebasingError: null,
};
},
computed: {
status() {
if (this.mr.rebaseInProgress || this.isMakingRequest) {
return 'loading';
}
if (!this.mr.canPushToSourceBranch && !this.mr.rebaseInProgress) {
return 'warning';
}
return 'success';
}, },
computed: { showDisabledButton() {
status() { return ['failed', 'loading'].includes(this.status);
if (this.mr.rebaseInProgress || this.isMakingRequest) {
return 'loading';
}
if (!this.mr.canPushToSourceBranch && !this.mr.rebaseInProgress) {
return 'warning';
}
return 'success';
},
showDisabledButton() {
return ['failed', 'loading'].includes(this.status);
},
}, },
methods: { },
rebase() { methods: {
this.isMakingRequest = true; rebase() {
this.rebasingError = null; this.isMakingRequest = true;
this.rebasingError = null;
this.service.rebase() this.service
.then(() => { .rebase()
simplePoll(this.checkRebaseStatus); .then(() => {
}) simplePoll(this.checkRebaseStatus);
.catch((error) => { })
this.rebasingError = error.merge_error; .catch(error => {
this.rebasingError = error.merge_error;
this.isMakingRequest = false;
Flash('Something went wrong. Please try again.');
});
},
checkRebaseStatus(continuePolling, stopPolling) {
this.service
.poll()
.then(res => res.data)
.then(res => {
if (res.rebase_in_progress) {
continuePolling();
} else {
this.isMakingRequest = false; this.isMakingRequest = false;
Flash('Something went wrong. Please try again.');
});
},
checkRebaseStatus(continuePolling, stopPolling) {
this.service.poll()
.then(res => res.data)
.then((res) => {
if (res.rebase_in_progress) {
continuePolling();
} else {
this.isMakingRequest = false;
if (res.merge_error && res.merge_error.length) {
this.rebasingError = res.merge_error;
Flash('Something went wrong. Please try again.');
}
eventHub.$emit('MRWidgetUpdateRequested'); if (res.merge_error && res.merge_error.length) {
stopPolling(); this.rebasingError = res.merge_error;
Flash('Something went wrong. Please try again.');
} }
})
.catch(() => { eventHub.$emit('MRWidgetUpdateRequested');
this.isMakingRequest = false;
Flash('Something went wrong. Please try again.');
stopPolling(); stopPolling();
}); }
}, })
.catch(() => {
this.isMakingRequest = false;
Flash('Something went wrong. Please try again.');
stopPolling();
});
}, },
}; },
};
</script> </script>
<template> <template>
<div class="mr-widget-body media"> <div class="mr-widget-body media">
......
...@@ -24,9 +24,10 @@ export default { ...@@ -24,9 +24,10 @@ export default {
methods: { methods: {
removeWIP() { removeWIP() {
this.isMakingRequest = true; this.isMakingRequest = true;
this.service.removeWIP() this.service
.removeWIP()
.then(res => res.data) .then(res => res.data)
.then((data) => { .then(data => {
eventHub.$emit('UpdateWidgetData', data); eventHub.$emit('UpdateWidgetData', data);
new window.Flash('The merge request can now be merged.', 'notice'); // eslint-disable-line new window.Flash('The merge request can now be merged.', 'notice'); // eslint-disable-line
$('.merge-request .detail-page-description .title').text(this.mr.title); $('.merge-request .detail-page-description .title').text(this.mr.title);
......
<script> <script>
import Project from '~/pages/projects/project'; import Project from '~/pages/projects/project';
import SmartInterval from '~/smart_interval'; import SmartInterval from '~/smart_interval';
import createFlash from '../flash'; import createFlash from '../flash';
...@@ -100,8 +99,11 @@ export default { ...@@ -100,8 +99,11 @@ export default {
return !!this.mr.relatedLinks && !this.mr.isNothingToMergeState; return !!this.mr.relatedLinks && !this.mr.isNothingToMergeState;
}, },
shouldRenderSourceBranchRemovalStatus() { shouldRenderSourceBranchRemovalStatus() {
return !this.mr.canRemoveSourceBranch && this.mr.shouldRemoveSourceBranch && return (
(!this.mr.isNothingToMergeState && !this.mr.isMergedState); !this.mr.canRemoveSourceBranch &&
this.mr.shouldRemoveSourceBranch &&
(!this.mr.isNothingToMergeState && !this.mr.isMergedState)
);
}, },
}, },
created() { created() {
...@@ -133,9 +135,10 @@ export default { ...@@ -133,9 +135,10 @@ export default {
return new MRWidgetService(endpoints); return new MRWidgetService(endpoints);
}, },
checkStatus(cb) { checkStatus(cb) {
return this.service.checkStatus() return this.service
.checkStatus()
.then(res => res.data) .then(res => res.data)
.then((data) => { .then(data => {
this.handleNotification(data); this.handleNotification(data);
this.mr.setData(data); this.mr.setData(data);
this.setFaviconHelper(); this.setFaviconHelper();
...@@ -172,20 +175,24 @@ export default { ...@@ -172,20 +175,24 @@ export default {
return Promise.resolve(); return Promise.resolve();
}, },
fetchDeployments() { fetchDeployments() {
return this.service.fetchDeployments() return this.service
.fetchDeployments()
.then(res => res.data) .then(res => res.data)
.then((data) => { .then(data => {
if (data.length) { if (data.length) {
this.mr.deployments = data; this.mr.deployments = data;
} }
}) })
.catch(() => { .catch(() => {
createFlash('Something went wrong while fetching the environments for this merge request. Please try again.'); createFlash(
'Something went wrong while fetching the environments for this merge request. Please try again.',
);
}); });
}, },
fetchActionsContent() { fetchActionsContent() {
this.service.fetchMergeActionsContent() this.service
.then((res) => { .fetchMergeActionsContent()
.then(res => {
if (res.data) { if (res.data) {
const el = document.createElement('div'); const el = document.createElement('div');
el.innerHTML = res.data; el.innerHTML = res.data;
...@@ -212,22 +219,22 @@ export default { ...@@ -212,22 +219,22 @@ export default {
this.pollingInterval.stopTimer(); this.pollingInterval.stopTimer();
}, },
bindEventHubListeners() { bindEventHubListeners() {
eventHub.$on('MRWidgetUpdateRequested', (cb) => { eventHub.$on('MRWidgetUpdateRequested', cb => {
this.checkStatus(cb); this.checkStatus(cb);
}); });
// `params` should be an Array contains a Boolean, like `[true]` // `params` should be an Array contains a Boolean, like `[true]`
// Passing parameter as Boolean didn't work. // Passing parameter as Boolean didn't work.
eventHub.$on('SetBranchRemoveFlag', (params) => { eventHub.$on('SetBranchRemoveFlag', params => {
[this.mr.isRemovingSourceBranch] = params; [this.mr.isRemovingSourceBranch] = params;
}); });
eventHub.$on('FailedToMerge', (mergeError) => { eventHub.$on('FailedToMerge', mergeError => {
this.mr.state = 'failedToMerge'; this.mr.state = 'failedToMerge';
this.mr.mergeError = mergeError; this.mr.mergeError = mergeError;
}); });
eventHub.$on('UpdateWidgetData', (data) => { eventHub.$on('UpdateWidgetData', data => {
this.mr.setData(data); this.mr.setData(data);
}); });
......
...@@ -118,7 +118,9 @@ export default { ...@@ -118,7 +118,9 @@ export default {
this.rectYAxisLabelDims.height != null ? this.rectYAxisLabelDims.height / 2 : 0; this.rectYAxisLabelDims.height != null ? this.rectYAxisLabelDims.height / 2 : 0;
const yCoord = this.vbHeight / 2 + rectWidth - 5; const yCoord = this.vbHeight / 2 + rectWidth - 5;
return `translate(${this.minX + this.yAxisTextTransformPadding}, ${yCoord}) rotate(-${this.yAxisTextRotation})`; return `translate(${this.minX + this.yAxisTextTransformPadding}, ${yCoord}) rotate(-${
this.yAxisTextRotation
})`;
}, },
}, },
mounted() { mounted() {
...@@ -207,8 +209,7 @@ export default { ...@@ -207,8 +209,7 @@ export default {
renderedYAxis.selectAll('.tick').each(function createTickLines(d, i) { renderedYAxis.selectAll('.tick').each(function createTickLines(d, i) {
if (i > 0) { if (i > 0) {
d3 d3.select(this)
.select(this)
.select('line') .select('line')
.attr('x2', width) .attr('x2', width)
.attr('class', 'axis-tick'); .attr('class', 'axis-tick');
...@@ -217,8 +218,7 @@ export default { ...@@ -217,8 +218,7 @@ export default {
// Add the panning capabilities // Add the panning capabilities
if (this.isPanAvailable) { if (this.isPanAvailable) {
d3 d3.select(this.$refs.baseSvg)
.select(this.$refs.baseSvg)
.call(this.zoom) .call(this.zoom)
.on('wheel.zoom', null); // This disables the pan of the graph with the scroll of the mouse wheel .on('wheel.zoom', null); // This disables the pan of the graph with the scroll of the mouse wheel
} }
......
<script> <script>
/* eslint-disable vue/require-default-prop */ /* eslint-disable vue/require-default-prop */
export default { export default {
name: 'DeprecatedModal', // use GlModal instead name: 'DeprecatedModal', // use GlModal instead
props: { props: {
id: { id: {
type: String, type: String,
required: false, required: false,
},
title: {
type: String,
required: false,
},
text: {
type: String,
required: false,
},
hideFooter: {
type: Boolean,
required: false,
default: false,
},
kind: {
type: String,
required: false,
default: 'primary',
},
modalDialogClass: {
type: String,
required: false,
default: '',
},
closeKind: {
type: String,
required: false,
default: 'default',
},
closeButtonLabel: {
type: String,
required: false,
default: 'Cancel',
},
primaryButtonLabel: {
type: String,
required: false,
default: '',
},
secondaryButtonLabel: {
type: String,
required: false,
default: '',
},
submitDisabled: {
type: Boolean,
required: false,
default: false,
},
}, },
title: {
type: String,
required: false,
},
text: {
type: String,
required: false,
},
hideFooter: {
type: Boolean,
required: false,
default: false,
},
kind: {
type: String,
required: false,
default: 'primary',
},
modalDialogClass: {
type: String,
required: false,
default: '',
},
closeKind: {
type: String,
required: false,
default: 'default',
},
closeButtonLabel: {
type: String,
required: false,
default: 'Cancel',
},
primaryButtonLabel: {
type: String,
required: false,
default: '',
},
secondaryButtonLabel: {
type: String,
required: false,
default: '',
},
submitDisabled: {
type: Boolean,
required: false,
default: false,
},
},
computed: { computed: {
btnKindClass() { btnKindClass() {
return { return {
[`btn-${this.kind}`]: true, [`btn-${this.kind}`]: true,
}; };
}, },
btnCancelKindClass() { btnCancelKindClass() {
return { return {
[`btn-${this.closeKind}`]: true, [`btn-${this.closeKind}`]: true,
}; };
},
}, },
},
methods: { methods: {
emitCancel(event) { emitCancel(event) {
this.$emit('cancel', event); this.$emit('cancel', event);
}, },
emitSubmit(event) { emitSubmit(event) {
this.$emit('submit', event); this.$emit('submit', event);
},
}, },
}; },
};
</script> </script>
<template> <template>
......
...@@ -583,7 +583,5 @@ const fileNameIcons = { ...@@ -583,7 +583,5 @@ const fileNameIcons = {
}; };
export default function getIconForFile(name) { export default function getIconForFile(name) {
return fileNameIcons[name] || return fileNameIcons[name] || fileExtensionIcons[name ? name.split('.').pop() : ''] || '';
fileExtensionIcons[name ? name.split('.').pop() : ''] ||
'';
} }
<script> <script>
// only allow classes in images.scss e.g. s12 // only allow classes in images.scss e.g. s12
const validSizes = [8, 10, 12, 16, 18, 24, 32, 48, 72]; const validSizes = [8, 10, 12, 16, 18, 24, 32, 48, 72];
let iconValidator = () => true; let iconValidator = () => true;
......
<script> <script>
import icon from '../../../vue_shared/components/icon.vue'; import icon from '../../../vue_shared/components/icon.vue';
export default { export default {
components: { components: {
icon, icon,
},
props: {
isLocked: {
type: Boolean,
default: false,
required: false,
}, },
props: { isConfidential: {
isLocked: { type: Boolean,
type: Boolean, default: false,
default: false, required: false,
required: false,
},
isConfidential: {
type: Boolean,
default: false,
required: false,
},
}, },
computed: { },
warningIcon() { computed: {
if (this.isConfidential) return 'eye-slash'; warningIcon() {
if (this.isLocked) return 'lock'; if (this.isConfidential) return 'eye-slash';
if (this.isLocked) return 'lock';
return ''; return '';
},
isLockedAndConfidential() {
return this.isConfidential && this.isLocked;
},
}, },
}; isLockedAndConfidential() {
return this.isConfidential && this.isLocked;
},
},
};
</script> </script>
<template> <template>
<div class="issuable-note-warning"> <div class="issuable-note-warning">
......
<script> <script>
/* eslint-disable vue/require-default-prop */ /* eslint-disable vue/require-default-prop */
/* This is a re-usable vue component for rendering a button /* This is a re-usable vue component for rendering a button
that will probably be sending off ajax requests and need that will probably be sending off ajax requests and need
to show the loading status by setting the `loading` option. to show the loading status by setting the `loading` option.
This can also be used for initial page load when you don't This can also be used for initial page load when you don't
...@@ -17,34 +17,34 @@ ...@@ -17,34 +17,34 @@
*/ */
export default { export default {
props: { props: {
loading: { loading: {
type: Boolean, type: Boolean,
required: false, required: false,
default: false, default: false,
},
disabled: {
type: Boolean,
required: false,
default: false,
},
label: {
type: String,
required: false,
},
containerClass: {
type: [String, Array, Object],
required: false,
default: 'btn btn-align-content',
},
}, },
methods: { disabled: {
onClick(e) { type: Boolean,
this.$emit('click', e); required: false,
}, default: false,
}, },
}; label: {
type: String,
required: false,
},
containerClass: {
type: [String, Array, Object],
required: false,
default: 'btn btn-align-content',
},
},
methods: {
onClick(e) {
this.$emit('click', e);
},
},
};
</script> </script>
<template> <template>
......
<script> <script>
import $ from 'jquery'; import $ from 'jquery';
import { s__ } from '~/locale'; import { s__ } from '~/locale';
import Flash from '../../../flash'; import Flash from '../../../flash';
import GLForm from '../../../gl_form'; import GLForm from '../../../gl_form';
import markdownHeader from './header.vue'; import markdownHeader from './header.vue';
import markdownToolbar from './toolbar.vue'; import markdownToolbar from './toolbar.vue';
import icon from '../icon.vue'; import icon from '../icon.vue';
export default { export default {
components: { components: {
markdownHeader, markdownHeader,
markdownToolbar, markdownToolbar,
icon, icon,
},
props: {
markdownPreviewPath: {
type: String,
required: false,
default: '',
}, },
props: { markdownDocsPath: {
markdownPreviewPath: { type: String,
type: String, required: true,
required: false,
default: '',
},
markdownDocsPath: {
type: String,
required: true,
},
markdownVersion: {
type: Number,
required: false,
default: 0,
},
addSpacingClasses: {
type: Boolean,
required: false,
default: true,
},
quickActionsDocsPath: {
type: String,
required: false,
default: '',
},
canAttachFile: {
type: Boolean,
required: false,
default: true,
},
enableAutocomplete: {
type: Boolean,
required: false,
default: true,
},
}, },
data() { markdownVersion: {
return { type: Number,
markdownPreview: '', required: false,
referencedCommands: '', default: 0,
referencedUsers: '',
markdownPreviewLoading: false,
previewMarkdown: false,
};
}, },
computed: { addSpacingClasses: {
shouldShowReferencedUsers() { type: Boolean,
const referencedUsersThreshold = 10; required: false,
return this.referencedUsers.length >= referencedUsersThreshold; default: true,
},
}, },
mounted() { quickActionsDocsPath: {
/* type: String,
GLForm class handles all the toolbar buttons required: false,
*/ default: '',
return new GLForm($(this.$refs['gl-form']), {
emojis: this.enableAutocomplete,
members: this.enableAutocomplete,
issues: this.enableAutocomplete,
mergeRequests: this.enableAutocomplete,
epics: this.enableAutocomplete,
milestones: this.enableAutocomplete,
labels: this.enableAutocomplete,
snippets: this.enableAutocomplete,
});
}, },
beforeDestroy() { canAttachFile: {
const glForm = $(this.$refs['gl-form']).data('glForm'); type: Boolean,
if (glForm) { required: false,
glForm.destroy(); default: true,
} },
enableAutocomplete: {
type: Boolean,
required: false,
default: true,
}, },
methods: { },
showPreviewTab() { data() {
if (this.previewMarkdown) return; return {
markdownPreview: '',
referencedCommands: '',
referencedUsers: '',
markdownPreviewLoading: false,
previewMarkdown: false,
};
},
computed: {
shouldShowReferencedUsers() {
const referencedUsersThreshold = 10;
return this.referencedUsers.length >= referencedUsersThreshold;
},
},
mounted() {
/*
GLForm class handles all the toolbar buttons
*/
return new GLForm($(this.$refs['gl-form']), {
emojis: this.enableAutocomplete,
members: this.enableAutocomplete,
issues: this.enableAutocomplete,
mergeRequests: this.enableAutocomplete,
epics: this.enableAutocomplete,
milestones: this.enableAutocomplete,
labels: this.enableAutocomplete,
snippets: this.enableAutocomplete,
});
},
beforeDestroy() {
const glForm = $(this.$refs['gl-form']).data('glForm');
if (glForm) {
glForm.destroy();
}
},
methods: {
showPreviewTab() {
if (this.previewMarkdown) return;
this.previewMarkdown = true; this.previewMarkdown = true;
/* /*
Can't use `$refs` as the component is technically in the parent component Can't use `$refs` as the component is technically in the parent component
so we access the VNode & then get the element so we access the VNode & then get the element
*/ */
const text = this.$slots.textarea[0].elm.value; const text = this.$slots.textarea[0].elm.value;
if (text) { if (text) {
this.markdownPreviewLoading = true; this.markdownPreviewLoading = true;
this.$http this.$http
.post(this.versionedPreviewPath(), { text }) .post(this.versionedPreviewPath(), { text })
.then(resp => resp.json()) .then(resp => resp.json())
.then(data => this.renderMarkdown(data)) .then(data => this.renderMarkdown(data))
.catch(() => new Flash(s__('Error loading markdown preview'))); .catch(() => new Flash(s__('Error loading markdown preview')));
} else { } else {
this.renderMarkdown(); this.renderMarkdown();
} }
}, },
showWriteTab() { showWriteTab() {
this.markdownPreview = ''; this.markdownPreview = '';
this.previewMarkdown = false; this.previewMarkdown = false;
}, },
renderMarkdown(data = {}) { renderMarkdown(data = {}) {
this.markdownPreviewLoading = false; this.markdownPreviewLoading = false;
this.markdownPreview = data.body || 'Nothing to preview.'; this.markdownPreview = data.body || 'Nothing to preview.';
if (data.references) { if (data.references) {
this.referencedCommands = data.references.commands; this.referencedCommands = data.references.commands;
this.referencedUsers = data.references.users; this.referencedUsers = data.references.users;
} }
this.$nextTick(() => { this.$nextTick(() => {
$(this.$refs['markdown-preview']).renderGFM(); $(this.$refs['markdown-preview']).renderGFM();
}); });
}, },
versionedPreviewPath() { versionedPreviewPath() {
const { markdownPreviewPath, markdownVersion } = this; const { markdownPreviewPath, markdownVersion } = this;
return `${markdownPreviewPath}${ return `${markdownPreviewPath}${
markdownPreviewPath.indexOf('?') === -1 ? '?' : '&' markdownPreviewPath.indexOf('?') === -1 ? '?' : '&'
}markdown_version=${markdownVersion}`; }markdown_version=${markdownVersion}`;
},
}, },
}; },
};
</script> </script>
<template> <template>
......
<script> <script>
import $ from 'jquery'; import $ from 'jquery';
import tooltip from '../../directives/tooltip'; import tooltip from '../../directives/tooltip';
import toolbarButton from './toolbar_button.vue'; import toolbarButton from './toolbar_button.vue';
import icon from '../icon.vue'; import icon from '../icon.vue';
export default { export default {
directives: { directives: {
tooltip, tooltip,
},
components: {
toolbarButton,
icon,
},
props: {
previewMarkdown: {
type: Boolean,
required: true,
}, },
components: { },
toolbarButton, computed: {
icon, mdTable() {
return [
'| header | header |',
'| ------ | ------ |',
'| cell | cell |',
'| cell | cell |',
].join('\n');
}, },
props: { },
previewMarkdown: { mounted() {
type: Boolean, $(document).on('markdown-preview:show.vue', this.previewMarkdownTab);
required: true, $(document).on('markdown-preview:hide.vue', this.writeMarkdownTab);
}, },
beforeDestroy() {
$(document).off('markdown-preview:show.vue', this.previewMarkdownTab);
$(document).off('markdown-preview:hide.vue', this.writeMarkdownTab);
},
methods: {
isValid(form) {
return (
!form ||
(form.find('.js-vue-markdown-field').length && $(this.$el).closest('form')[0] === form[0])
);
}, },
computed: {
mdTable() {
return [
'| header | header |',
'| ------ | ------ |',
'| cell | cell |',
'| cell | cell |',
].join('\n');
},
},
mounted() {
$(document).on('markdown-preview:show.vue', this.previewMarkdownTab);
$(document).on('markdown-preview:hide.vue', this.writeMarkdownTab);
},
beforeDestroy() {
$(document).off('markdown-preview:show.vue', this.previewMarkdownTab);
$(document).off('markdown-preview:hide.vue', this.writeMarkdownTab);
},
methods: {
isValid(form) {
return !form ||
form.find('.js-vue-markdown-field').length &&
$(this.$el).closest('form')[0] === form[0];
},
previewMarkdownTab(event, form) { previewMarkdownTab(event, form) {
if (event.target.blur) event.target.blur(); if (event.target.blur) event.target.blur();
if (!this.isValid(form)) return; if (!this.isValid(form)) return;
this.$emit('preview-markdown'); this.$emit('preview-markdown');
}, },
writeMarkdownTab(event, form) { writeMarkdownTab(event, form) {
if (event.target.blur) event.target.blur(); if (event.target.blur) event.target.blur();
if (!this.isValid(form)) return; if (!this.isValid(form)) return;
this.$emit('write-markdown'); this.$emit('write-markdown');
},
}, },
}; },
};
</script> </script>
<template> <template>
......
<script> <script>
import { Link } from '@gitlab-org/gitlab-ui'; import { Link } from '@gitlab-org/gitlab-ui';
export default { export default {
components: { components: {
'gl-link': Link, 'gl-link': Link,
},
props: {
markdownDocsPath: {
type: String,
required: true,
}, },
props: { quickActionsDocsPath: {
markdownDocsPath: { type: String,
type: String, required: false,
required: true, default: '',
},
quickActionsDocsPath: {
type: String,
required: false,
default: '',
},
canAttachFile: {
type: Boolean,
required: false,
default: true,
},
}, },
computed: { canAttachFile: {
hasQuickActionsDocsPath() { type: Boolean,
return this.quickActionsDocsPath !== ''; required: false,
}, default: true,
}, },
}; },
computed: {
hasQuickActionsDocsPath() {
return this.quickActionsDocsPath !== '';
},
},
};
</script> </script>
<template> <template>
......
<script> <script>
import tooltip from '../../directives/tooltip'; import tooltip from '../../directives/tooltip';
import icon from '../icon.vue'; import icon from '../icon.vue';
export default { export default {
components: { components: {
icon, icon,
},
directives: {
tooltip,
},
props: {
buttonTitle: {
type: String,
required: true,
}, },
directives: { icon: {
tooltip, type: String,
required: true,
}, },
props: { tag: {
buttonTitle: { type: String,
type: String, required: true,
required: true,
},
icon: {
type: String,
required: true,
},
tag: {
type: String,
required: true,
},
tagBlock: {
type: String,
required: false,
default: '',
},
tagSelect: {
type: String,
required: false,
default: '',
},
prepend: {
type: Boolean,
required: false,
default: false,
},
}, },
}; tagBlock: {
type: String,
required: false,
default: '',
},
tagSelect: {
type: String,
required: false,
default: '',
},
prepend: {
type: Boolean,
required: false,
default: false,
},
},
};
</script> </script>
<template> <template>
......
...@@ -41,7 +41,8 @@ export default { ...@@ -41,7 +41,8 @@ export default {
// Find metric timestamp which is closest to deploymentTime // Find metric timestamp which is closest to deploymentTime
timestampDiff = Math.abs(metricTimestamps[0] - median); timestampDiff = Math.abs(metricTimestamps[0] - median);
metricTimestamps.forEach((timestamp, index) => { metricTimestamps.forEach((timestamp, index) => {
if (index === 0) { // Skip first element if (index === 0) {
// Skip first element
return; return;
} }
......
<script> <script>
/** /**
* Common component to render a placeholder note and user information. * Common component to render a placeholder note and user information.
* *
* This component needs to be used with a vuex store. * This component needs to be used with a vuex store.
* That vuex store needs to have a `getUserData` getter that contains * That vuex store needs to have a `getUserData` getter that contains
* { * {
* path: String, * path: String,
* avatar_url: String, * avatar_url: String,
* name: String, * name: String,
* username: String, * username: String,
* } * }
* *
* @example * @example
* <placeholder-note * <placeholder-note
* :note="{body: 'This is a note'}" * :note="{body: 'This is a note'}"
* /> * />
*/ */
import { mapGetters } from 'vuex'; import { mapGetters } from 'vuex';
import userAvatarLink from '../user_avatar/user_avatar_link.vue'; import userAvatarLink from '../user_avatar/user_avatar_link.vue';
export default { export default {
name: 'PlaceholderNote', name: 'PlaceholderNote',
components: { components: {
userAvatarLink, userAvatarLink,
},
props: {
note: {
type: Object,
required: true,
}, },
props: { },
note: { computed: {
type: Object, ...mapGetters(['getUserData']),
required: true, },
}, };
},
computed: {
...mapGetters([
'getUserData',
]),
},
};
</script> </script>
<template> <template>
......
<script> <script>
/** /**
* Common component to render a placeholder system note. * Common component to render a placeholder system note.
* *
* @example * @example
* <placeholder-system-note * <placeholder-system-note
* :note="{ body: 'Commands are being applied'}" * :note="{ body: 'Commands are being applied'}"
* /> * />
*/ */
export default { export default {
name: 'PlaceholderSystemNote', name: 'PlaceholderSystemNote',
props: { props: {
note: { note: {
type: Object, type: Object,
required: true, required: true,
},
}, },
}; },
};
</script> </script>
<template> <template>
......
<script> <script>
export default { export default {
props: { props: {
startSize: { startSize: {
type: Number, type: Number,
required: true, required: true,
},
side: {
type: String,
required: true,
},
minSize: {
type: Number,
required: false,
default: 0,
},
maxSize: {
type: Number,
required: false,
default: Number.MAX_VALUE,
},
enabled: {
type: Boolean,
required: false,
default: true,
},
}, },
data() { side: {
return { type: String,
size: this.startSize, required: true,
};
}, },
computed: { minSize: {
className() { type: Number,
return `drag-${this.side}`; required: false,
}, default: 0,
cursorStyle() {
if (this.enabled) {
return { cursor: 'ew-resize' };
}
return {};
},
}, },
methods: { maxSize: {
resetSize(e) { type: Number,
e.preventDefault(); required: false,
this.$emit('resize-start', this.size); default: Number.MAX_VALUE,
},
enabled: {
type: Boolean,
required: false,
default: true,
},
},
data() {
return {
size: this.startSize,
};
},
computed: {
className() {
return `drag-${this.side}`;
},
cursorStyle() {
if (this.enabled) {
return { cursor: 'ew-resize' };
}
return {};
},
},
methods: {
resetSize(e) {
e.preventDefault();
this.$emit('resize-start', this.size);
this.size = this.startSize; this.size = this.startSize;
this.$emit('update:size', this.size); this.$emit('update:size', this.size);
// End resizing on next tick so that listeners can react to DOM changes // End resizing on next tick so that listeners can react to DOM changes
this.$nextTick(() => { this.$nextTick(() => {
this.$emit('resize-end', this.size); this.$emit('resize-end', this.size);
}); });
}, },
startDrag(e) { startDrag(e) {
if (this.enabled) { if (this.enabled) {
e.preventDefault();
this.startPos = e.clientX;
this.currentStartSize = this.size;
document.addEventListener('mousemove', this.drag);
document.addEventListener('mouseup', this.endDrag, { once: true });
this.$emit('resize-start', this.size);
}
},
drag(e) {
e.preventDefault(); e.preventDefault();
let moved = e.clientX - this.startPos; this.startPos = e.clientX;
if (this.side === 'left') moved = -moved; this.currentStartSize = this.size;
let newSize = this.currentStartSize + moved; document.addEventListener('mousemove', this.drag);
if (newSize < this.minSize) { document.addEventListener('mouseup', this.endDrag, { once: true });
newSize = this.minSize; this.$emit('resize-start', this.size);
} else if (newSize > this.maxSize) { }
newSize = this.maxSize; },
} drag(e) {
this.size = newSize; e.preventDefault();
let moved = e.clientX - this.startPos;
if (this.side === 'left') moved = -moved;
let newSize = this.currentStartSize + moved;
if (newSize < this.minSize) {
newSize = this.minSize;
} else if (newSize > this.maxSize) {
newSize = this.maxSize;
}
this.size = newSize;
this.$emit('update:size', newSize); this.$emit('update:size', newSize);
}, },
endDrag(e) { endDrag(e) {
e.preventDefault(); e.preventDefault();
document.removeEventListener('mousemove', this.drag); document.removeEventListener('mousemove', this.drag);
this.$emit('resize-end', this.size); this.$emit('resize-end', this.size);
},
}, },
}; },
};
</script> </script>
<template> <template>
......
<script> <script>
import Pikaday from 'pikaday'; import Pikaday from 'pikaday';
import { parsePikadayDate, pikadayToString } from '../../lib/utils/datefix'; import { parsePikadayDate, pikadayToString } from '../../lib/utils/datefix';
export default { export default {
name: 'DatePicker', name: 'DatePicker',
props: { props: {
label: { label: {
type: String, type: String,
required: false, required: false,
default: 'Date picker', default: 'Date picker',
},
selectedDate: {
type: Date,
required: false,
default: null,
},
minDate: {
type: Date,
required: false,
default: null,
},
maxDate: {
type: Date,
required: false,
default: null,
},
}, },
mounted() { selectedDate: {
this.calendar = new Pikaday({ type: Date,
field: this.$el.querySelector('.dropdown-menu-toggle'), required: false,
theme: 'gitlab-theme animate-picker', default: null,
format: 'yyyy-mm-dd', },
container: this.$el, minDate: {
defaultDate: this.selectedDate, type: Date,
setDefaultDate: !!this.selectedDate, required: false,
minDate: this.minDate, default: null,
maxDate: this.maxDate,
parse: dateString => parsePikadayDate(dateString),
toString: date => pikadayToString(date),
onSelect: this.selected.bind(this),
onClose: this.toggled.bind(this),
});
this.$el.append(this.calendar.el);
this.calendar.show();
}, },
beforeDestroy() { maxDate: {
this.calendar.destroy(); type: Date,
required: false,
default: null,
},
},
mounted() {
this.calendar = new Pikaday({
field: this.$el.querySelector('.dropdown-menu-toggle'),
theme: 'gitlab-theme animate-picker',
format: 'yyyy-mm-dd',
container: this.$el,
defaultDate: this.selectedDate,
setDefaultDate: !!this.selectedDate,
minDate: this.minDate,
maxDate: this.maxDate,
parse: dateString => parsePikadayDate(dateString),
toString: date => pikadayToString(date),
onSelect: this.selected.bind(this),
onClose: this.toggled.bind(this),
});
this.$el.append(this.calendar.el);
this.calendar.show();
},
beforeDestroy() {
this.calendar.destroy();
},
methods: {
selected(dateText) {
this.$emit('newDateSelected', this.calendar.toString(dateText));
}, },
methods: { toggled() {
selected(dateText) { this.$emit('hidePicker');
this.$emit('newDateSelected', this.calendar.toString(dateText));
},
toggled() {
this.$emit('hidePicker');
},
}, },
}; },
};
</script> </script>
<template> <template>
......
<script> <script>
/* This is a re-usable vue component for rendering a project avatar that
/* This is a re-usable vue component for rendering a project avatar that
does not need to link to the project's profile. The image and an optional does not need to link to the project's profile. The image and an optional
tooltip can be configured by props passed to this component. tooltip can be configured by props passed to this component.
...@@ -16,70 +15,70 @@ ...@@ -16,70 +15,70 @@
*/ */
import defaultAvatarUrl from 'images/no_avatar.png'; import defaultAvatarUrl from 'images/no_avatar.png';
import { placeholderImage } from '../../../lazy_loader'; import { placeholderImage } from '../../../lazy_loader';
import tooltip from '../../directives/tooltip'; import tooltip from '../../directives/tooltip';
export default { export default {
name: 'ProjectAvatarImage', name: 'ProjectAvatarImage',
directives: { directives: {
tooltip, tooltip,
},
props: {
lazy: {
type: Boolean,
required: false,
default: false,
},
imgSrc: {
type: String,
required: false,
default: defaultAvatarUrl,
},
cssClasses: {
type: String,
required: false,
default: '',
},
imgAlt: {
type: String,
required: false,
default: 'project avatar',
},
size: {
type: Number,
required: false,
default: 20,
},
tooltipText: {
type: String,
required: false,
default: '',
},
tooltipPlacement: {
type: String,
required: false,
default: 'top',
},
},
computed: {
// API response sends null when gravatar is disabled and
// we provide an empty string when we use it inside project avatar link.
// In both cases we should render the defaultAvatarUrl
sanitizedSource() {
return this.imgSrc === '' || this.imgSrc === null ? defaultAvatarUrl : this.imgSrc;
},
resultantSrcAttribute() {
return this.lazy ? placeholderImage : this.sanitizedSource;
}, },
props: { tooltipContainer() {
lazy: { return this.tooltipText ? 'body' : null;
type: Boolean,
required: false,
default: false,
},
imgSrc: {
type: String,
required: false,
default: defaultAvatarUrl,
},
cssClasses: {
type: String,
required: false,
default: '',
},
imgAlt: {
type: String,
required: false,
default: 'project avatar',
},
size: {
type: Number,
required: false,
default: 20,
},
tooltipText: {
type: String,
required: false,
default: '',
},
tooltipPlacement: {
type: String,
required: false,
default: 'top',
},
}, },
computed: { avatarSizeClass() {
// API response sends null when gravatar is disabled and return `s${this.size}`;
// we provide an empty string when we use it inside project avatar link.
// In both cases we should render the defaultAvatarUrl
sanitizedSource() {
return this.imgSrc === '' || this.imgSrc === null ? defaultAvatarUrl : this.imgSrc;
},
resultantSrcAttribute() {
return this.lazy ? placeholderImage : this.sanitizedSource;
},
tooltipContainer() {
return this.tooltipText ? 'body' : null;
},
avatarSizeClass() {
return `s${this.size}`;
},
}, },
}; },
};
</script> </script>
<template> <template>
......
<script> <script>
import DeprecatedModal from './deprecated_modal.vue'; import DeprecatedModal from './deprecated_modal.vue';
export default { export default {
name: 'RecaptchaModal', name: 'RecaptchaModal',
components: { components: {
DeprecatedModal, DeprecatedModal,
}, },
props: { props: {
html: { html: {
type: String, type: String,
required: false, required: false,
default: '', default: '',
},
}, },
},
data() { data() {
return { return {
script: {}, script: {},
scriptSrc: 'https://www.google.com/recaptcha/api.js', scriptSrc: 'https://www.google.com/recaptcha/api.js',
}; };
}, },
watch: { watch: {
html() { html() {
this.appendRecaptchaScript(); this.appendRecaptchaScript();
},
}, },
},
mounted() { mounted() {
window.recaptchaDialogCallback = this.submit.bind(this); window.recaptchaDialogCallback = this.submit.bind(this);
}, },
methods: { methods: {
appendRecaptchaScript() { appendRecaptchaScript() {
this.removeRecaptchaScript(); this.removeRecaptchaScript();
const script = document.createElement('script'); const script = document.createElement('script');
script.src = this.scriptSrc; script.src = this.scriptSrc;
script.classList.add('js-recaptcha-script'); script.classList.add('js-recaptcha-script');
script.async = true; script.async = true;
script.defer = true; script.defer = true;
this.script = script; this.script = script;
document.body.appendChild(script); document.body.appendChild(script);
}, },
removeRecaptchaScript() { removeRecaptchaScript() {
if (this.script instanceof Element) this.script.remove(); if (this.script instanceof Element) this.script.remove();
}, },
close() { close() {
this.removeRecaptchaScript(); this.removeRecaptchaScript();
this.$emit('close'); this.$emit('close');
}, },
submit() { submit() {
this.$el.querySelector('form').submit(); this.$el.querySelector('form').submit();
},
}, },
}; },
};
</script> </script>
<template> <template>
......
<script> <script>
import datePicker from '../pikaday.vue'; import datePicker from '../pikaday.vue';
import toggleSidebar from './toggle_sidebar.vue'; import toggleSidebar from './toggle_sidebar.vue';
import collapsedCalendarIcon from './collapsed_calendar_icon.vue'; import collapsedCalendarIcon from './collapsed_calendar_icon.vue';
import { dateInWords } from '../../../lib/utils/datetime_utility'; import { dateInWords } from '../../../lib/utils/datetime_utility';
export default { export default {
name: 'SidebarDatePicker', name: 'SidebarDatePicker',
components: { components: {
datePicker, datePicker,
toggleSidebar, toggleSidebar,
collapsedCalendarIcon, collapsedCalendarIcon,
}, },
props: { props: {
blockClass: { blockClass: {
type: String, type: String,
required: false, required: false,
default: '', default: '',
}, },
collapsed: { collapsed: {
type: Boolean, type: Boolean,
required: false, required: false,
default: true, default: true,
}, },
showToggleSidebar: { showToggleSidebar: {
type: Boolean, type: Boolean,
required: false, required: false,
default: false, default: false,
}, },
isLoading: { isLoading: {
type: Boolean, type: Boolean,
required: false, required: false,
default: false, default: false,
}, },
editable: { editable: {
type: Boolean, type: Boolean,
required: false, required: false,
default: false, default: false,
}, },
label: { label: {
type: String, type: String,
required: false, required: false,
default: 'Date picker', default: 'Date picker',
}, },
selectedDate: { selectedDate: {
type: Date, type: Date,
required: false, required: false,
default: null, default: null,
}, },
minDate: { minDate: {
type: Date, type: Date,
required: false, required: false,
default: null, default: null,
}, },
maxDate: { maxDate: {
type: Date, type: Date,
required: false, required: false,
default: null, default: null,
}, },
}, },
data() { data() {
return { return {
editing: false, editing: false,
}; };
}, },
computed: { computed: {
selectedAndEditable() { selectedAndEditable() {
return this.selectedDate && this.editable; return this.selectedDate && this.editable;
}, },
selectedDateWords() { selectedDateWords() {
return dateInWords(this.selectedDate, true); return dateInWords(this.selectedDate, true);
}, },
collapsedText() { collapsedText() {
return this.selectedDateWords ? this.selectedDateWords : 'None'; return this.selectedDateWords ? this.selectedDateWords : 'None';
}, },
}, },
methods: { methods: {
stopEditing() { stopEditing() {
this.editing = false; this.editing = false;
}, },
toggleDatePicker() { toggleDatePicker() {
this.editing = !this.editing; this.editing = !this.editing;
}, },
newDateSelected(date = null) { newDateSelected(date = null) {
this.date = date; this.date = date;
this.editing = false; this.editing = false;
this.$emit('saveDate', date); this.$emit('saveDate', date);
}, },
toggleSidebar() { toggleSidebar() {
this.$emit('toggleCollapse'); this.$emit('toggleCollapse');
}, },
}, },
}; };
</script> </script>
<template> <template>
......
<script> <script>
import { s__ } from '../../locale'; import { s__ } from '../../locale';
const PAGINATION_UI_BUTTON_LIMIT = 4; const PAGINATION_UI_BUTTON_LIMIT = 4;
const UI_LIMIT = 6; const UI_LIMIT = 6;
const SPREAD = '...'; const SPREAD = '...';
const PREV = s__('Pagination|Prev'); const PREV = s__('Pagination|Prev');
const NEXT = s__('Pagination|Next'); const NEXT = s__('Pagination|Next');
const FIRST = s__('Pagination|« First'); const FIRST = s__('Pagination|« First');
const LAST = s__('Pagination|Last »'); const LAST = s__('Pagination|Last »');
export default { export default {
props: { props: {
/** /**
This function will take the information given by the pagination component This function will take the information given by the pagination component
Here is an example `change` method: Here is an example `change` method:
...@@ -20,12 +20,12 @@ ...@@ -20,12 +20,12 @@
gl.utils.visitUrl(`?page=${pagenum}`); gl.utils.visitUrl(`?page=${pagenum}`);
}, },
*/ */
change: { change: {
type: Function, type: Function,
required: true, required: true,
}, },
/** /**
pageInfo will come from the headers of the API call pageInfo will come from the headers of the API call
in the `.then` clause of the VueResource API call in the `.then` clause of the VueResource API call
there should be a function that contructs the pageInfo for this component there should be a function that contructs the pageInfo for this component
...@@ -41,94 +41,94 @@ ...@@ -41,94 +41,94 @@
previousPage: +headers['X-Prev-Page'], previousPage: +headers['X-Prev-Page'],
}); });
*/ */
pageInfo: { pageInfo: {
type: Object, type: Object,
required: true, required: true,
}, },
},
computed: {
prev() {
return this.pageInfo.previousPage;
},
next() {
return this.pageInfo.nextPage;
},
getItems() {
const total = this.pageInfo.totalPages;
const { page } = this.pageInfo;
const items = [];
if (page > 1) {
items.push({ title: FIRST, first: true });
}
if (page > 1) {
items.push({ title: PREV, prev: true });
} else {
items.push({ title: PREV, disabled: true, prev: true });
}
if (page > UI_LIMIT) items.push({ title: SPREAD, separator: true });
const start = Math.max(page - PAGINATION_UI_BUTTON_LIMIT, 1);
const end = Math.min(page + PAGINATION_UI_BUTTON_LIMIT, total);
for (let i = start; i <= end; i += 1) {
const isActive = i === page;
items.push({ title: i, active: isActive, page: true });
}
if (total - page > PAGINATION_UI_BUTTON_LIMIT) {
items.push({ title: SPREAD, separator: true, page: true });
}
if (page === total) {
items.push({ title: NEXT, disabled: true, next: true });
} else if (total - page >= 1) {
items.push({ title: NEXT, next: true });
}
if (total - page >= 1) {
items.push({ title: LAST, last: true });
}
return items;
},
showPagination() {
return this.pageInfo.totalPages > 1;
}, },
computed: { },
prev() { methods: {
return this.pageInfo.previousPage; changePage(text, isDisabled) {
}, if (isDisabled) return;
next() {
return this.pageInfo.nextPage; const { totalPages, nextPage, previousPage } = this.pageInfo;
},
getItems() { switch (text) {
const total = this.pageInfo.totalPages; case SPREAD:
const { page } = this.pageInfo; break;
const items = []; case LAST:
this.change(totalPages);
if (page > 1) { break;
items.push({ title: FIRST, first: true }); case NEXT:
} this.change(nextPage);
break;
if (page > 1) { case PREV:
items.push({ title: PREV, prev: true }); this.change(previousPage);
} else { break;
items.push({ title: PREV, disabled: true, prev: true }); case FIRST:
} this.change(1);
break;
if (page > UI_LIMIT) items.push({ title: SPREAD, separator: true }); default:
this.change(+text);
const start = Math.max(page - PAGINATION_UI_BUTTON_LIMIT, 1); break;
const end = Math.min(page + PAGINATION_UI_BUTTON_LIMIT, total); }
for (let i = start; i <= end; i += 1) {
const isActive = i === page;
items.push({ title: i, active: isActive, page: true });
}
if (total - page > PAGINATION_UI_BUTTON_LIMIT) {
items.push({ title: SPREAD, separator: true, page: true });
}
if (page === total) {
items.push({ title: NEXT, disabled: true, next: true });
} else if (total - page >= 1) {
items.push({ title: NEXT, next: true });
}
if (total - page >= 1) {
items.push({ title: LAST, last: true });
}
return items;
},
showPagination() {
return this.pageInfo.totalPages > 1;
},
}, },
methods: { hideOnSmallScreen(item) {
changePage(text, isDisabled) { return !item.first && !item.last && !item.next && !item.prev && !item.active;
if (isDisabled) return;
const { totalPages, nextPage, previousPage } = this.pageInfo;
switch (text) {
case SPREAD:
break;
case LAST:
this.change(totalPages);
break;
case NEXT:
this.change(nextPage);
break;
case PREV:
this.change(previousPage);
break;
case FIRST:
this.change(1);
break;
default:
this.change(+text);
break;
}
},
hideOnSmallScreen(item) {
return !item.first && !item.last && !item.next && !item.prev && !item.active;
},
}, },
}; },
};
</script> </script>
<template> <template>
<div <div
......
...@@ -11,9 +11,7 @@ export default { ...@@ -11,9 +11,7 @@ export default {
directives: { directives: {
tooltip, tooltip,
}, },
mixins: [ mixins: [timeagoMixin],
timeagoMixin,
],
props: { props: {
time: { time: {
type: String, type: String,
......
<script> <script>
import { s__ } from '../../locale'; import { s__ } from '../../locale';
import icon from './icon.vue'; import icon from './icon.vue';
const ICON_ON = 'status_success_borderless'; const ICON_ON = 'status_success_borderless';
const ICON_OFF = 'status_failed_borderless'; const ICON_OFF = 'status_failed_borderless';
const LABEL_ON = s__('ToggleButton|Toggle Status: ON'); const LABEL_ON = s__('ToggleButton|Toggle Status: ON');
const LABEL_OFF = s__('ToggleButton|Toggle Status: OFF'); const LABEL_OFF = s__('ToggleButton|Toggle Status: OFF');
export default { export default {
components: { components: {
icon, icon,
}, },
model: { model: {
prop: 'value', prop: 'value',
event: 'change', event: 'change',
}, },
props: { props: {
name: { name: {
type: String, type: String,
required: false, required: false,
default: null, default: null,
}, },
value: { value: {
type: Boolean, type: Boolean,
required: false, required: false,
default: null, default: null,
},
disabledInput: {
type: Boolean,
required: false,
default: false,
},
isLoading: {
type: Boolean,
required: false,
default: false,
},
}, },
disabledInput: {
type: Boolean,
required: false,
default: false,
},
isLoading: {
type: Boolean,
required: false,
default: false,
},
},
computed: { computed: {
toggleIcon() { toggleIcon() {
return this.value ? ICON_ON : ICON_OFF; return this.value ? ICON_ON : ICON_OFF;
}, },
ariaLabel() { ariaLabel() {
return this.value ? LABEL_ON : LABEL_OFF; return this.value ? LABEL_ON : LABEL_OFF;
},
}, },
},
methods: { methods: {
toggleFeature() { toggleFeature() {
if (!this.disabledInput) this.$emit('change', !this.value); if (!this.disabledInput) this.$emit('change', !this.value);
},
}, },
}; },
};
</script> </script>
<template> <template>
......
<script> <script>
/* This is a re-usable vue component for rendering a user avatar wrapped in /* This is a re-usable vue component for rendering a user avatar wrapped in
a clickable link (likely to the user's profile). The link, image, and a clickable link (likely to the user's profile). The link, image, and
tooltip can be configured by props passed to this component. tooltip can be configured by props passed to this component.
......
<script> <script>
/* This is a re-usable vue component for rendering a user avatar svg (typically /* This is a re-usable vue component for rendering a user avatar svg (typically
for a blank state). It will receive styles comparable to the user avatar, for a blank state). It will receive styles comparable to the user avatar,
but no image is loaded, it isn't wrapped in a link, and tooltips aren't supported. but no image is loaded, it isn't wrapped in a link, and tooltips aren't supported.
...@@ -42,4 +41,3 @@ export default { ...@@ -42,4 +41,3 @@ export default {
v-html="svg" v-html="svg"
/> />
</template> </template>
...@@ -4,10 +4,7 @@ ...@@ -4,10 +4,7 @@
* *
* Components need to have `scope`, `page` and `requestData` * Components need to have `scope`, `page` and `requestData`
*/ */
import { import { historyPushState, buildUrlWithCurrentLocation } from '../../lib/utils/common_utils';
historyPushState,
buildUrlWithCurrentLocation,
} from '../../lib/utils/common_utils';
export default { export default {
methods: { methods: {
...@@ -24,12 +21,14 @@ export default { ...@@ -24,12 +21,14 @@ export default {
// stop polling // stop polling
this.poll.stop(); this.poll.stop();
const queryString = Object.keys(parameters).map((parameter) => { const queryString = Object.keys(parameters)
const value = parameters[parameter]; .map(parameter => {
// update internal state for UI const value = parameters[parameter];
this[parameter] = value; // update internal state for UI
return `${parameter}=${encodeURIComponent(value)}`; this[parameter] = value;
}).join('&'); return `${parameter}=${encodeURIComponent(value)}`;
})
.join('&');
// update polling parameters // update polling parameters
this.requestData = parameters; this.requestData = parameters;
......
...@@ -6,7 +6,7 @@ export default class ListLabel { ...@@ -6,7 +6,7 @@ export default class ListLabel {
this.color = obj.color; this.color = obj.color;
this.textColor = obj.text_color; this.textColor = obj.text_color;
this.description = obj.description; this.description = obj.description;
this.priority = (obj.priority !== null) ? obj.priority : Infinity; this.priority = obj.priority !== null ? obj.priority : Infinity;
} }
} }
......
import { import { __, n__, s__, sprintf } from '../locale';
__,
n__,
s__,
sprintf,
} from '../locale';
export default (Vue) => { export default Vue => {
Vue.mixin({ Vue.mixin({
methods: { methods: {
/** /**
......
...@@ -21,7 +21,7 @@ Vue.http.interceptors.push((request, next) => { ...@@ -21,7 +21,7 @@ Vue.http.interceptors.push((request, next) => {
Vue.http.interceptors.push((request, next) => { Vue.http.interceptors.push((request, next) => {
request.headers.set(csrf.headerKey, csrf.token); request.headers.set(csrf.headerKey, csrf.token);
next((response) => { next(response => {
// Headers object has a `forEach` property that iterates through all values. // Headers object has a `forEach` property that iterates through all values.
const headers = {}; const headers = {};
......
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