Prettify issue_show and jobs modules
This commit is contained in:
parent
550f55745a
commit
9867eaf3ef
23 changed files with 1078 additions and 1084 deletions
|
@ -1,281 +1,279 @@
|
|||
<script>
|
||||
import Visibility from 'visibilityjs';
|
||||
import { visitUrl } from '../../lib/utils/url_utility';
|
||||
import Poll from '../../lib/utils/poll';
|
||||
import eventHub from '../event_hub';
|
||||
import Service from '../services/index';
|
||||
import Store from '../stores';
|
||||
import titleComponent from './title.vue';
|
||||
import descriptionComponent from './description.vue';
|
||||
import editedComponent from './edited.vue';
|
||||
import formComponent from './form.vue';
|
||||
import recaptchaModalImplementor from '../../vue_shared/mixins/recaptcha_modal_implementor';
|
||||
import Visibility from 'visibilityjs';
|
||||
import { visitUrl } from '../../lib/utils/url_utility';
|
||||
import Poll from '../../lib/utils/poll';
|
||||
import eventHub from '../event_hub';
|
||||
import Service from '../services/index';
|
||||
import Store from '../stores';
|
||||
import titleComponent from './title.vue';
|
||||
import descriptionComponent from './description.vue';
|
||||
import editedComponent from './edited.vue';
|
||||
import formComponent from './form.vue';
|
||||
import recaptchaModalImplementor from '../../vue_shared/mixins/recaptcha_modal_implementor';
|
||||
|
||||
export default {
|
||||
components: {
|
||||
descriptionComponent,
|
||||
titleComponent,
|
||||
editedComponent,
|
||||
formComponent,
|
||||
export default {
|
||||
components: {
|
||||
descriptionComponent,
|
||||
titleComponent,
|
||||
editedComponent,
|
||||
formComponent,
|
||||
},
|
||||
mixins: [recaptchaModalImplementor],
|
||||
props: {
|
||||
endpoint: {
|
||||
required: true,
|
||||
type: String,
|
||||
},
|
||||
mixins: [
|
||||
recaptchaModalImplementor,
|
||||
],
|
||||
props: {
|
||||
endpoint: {
|
||||
required: true,
|
||||
type: String,
|
||||
},
|
||||
updateEndpoint: {
|
||||
required: true,
|
||||
type: String,
|
||||
},
|
||||
canUpdate: {
|
||||
required: true,
|
||||
type: Boolean,
|
||||
},
|
||||
canDestroy: {
|
||||
required: true,
|
||||
type: Boolean,
|
||||
},
|
||||
showInlineEditButton: {
|
||||
type: Boolean,
|
||||
required: false,
|
||||
default: true,
|
||||
},
|
||||
showDeleteButton: {
|
||||
type: Boolean,
|
||||
required: false,
|
||||
default: true,
|
||||
},
|
||||
enableAutocomplete: {
|
||||
type: Boolean,
|
||||
required: false,
|
||||
default: true,
|
||||
},
|
||||
issuableRef: {
|
||||
type: String,
|
||||
required: true,
|
||||
},
|
||||
initialTitleHtml: {
|
||||
type: String,
|
||||
required: true,
|
||||
},
|
||||
initialTitleText: {
|
||||
type: String,
|
||||
required: true,
|
||||
},
|
||||
initialDescriptionHtml: {
|
||||
type: String,
|
||||
required: false,
|
||||
default: '',
|
||||
},
|
||||
initialDescriptionText: {
|
||||
type: String,
|
||||
required: false,
|
||||
default: '',
|
||||
},
|
||||
initialTaskStatus: {
|
||||
type: String,
|
||||
required: false,
|
||||
default: '',
|
||||
},
|
||||
updatedAt: {
|
||||
type: String,
|
||||
required: false,
|
||||
default: '',
|
||||
},
|
||||
updatedByName: {
|
||||
type: String,
|
||||
required: false,
|
||||
default: '',
|
||||
},
|
||||
updatedByPath: {
|
||||
type: String,
|
||||
required: false,
|
||||
default: '',
|
||||
},
|
||||
issuableTemplates: {
|
||||
type: Array,
|
||||
required: false,
|
||||
default: () => [],
|
||||
},
|
||||
markdownPreviewPath: {
|
||||
type: String,
|
||||
required: true,
|
||||
},
|
||||
markdownDocsPath: {
|
||||
type: String,
|
||||
required: true,
|
||||
},
|
||||
markdownVersion: {
|
||||
type: Number,
|
||||
required: false,
|
||||
default: 0,
|
||||
},
|
||||
projectPath: {
|
||||
type: String,
|
||||
required: true,
|
||||
},
|
||||
projectNamespace: {
|
||||
type: String,
|
||||
required: true,
|
||||
},
|
||||
issuableType: {
|
||||
type: String,
|
||||
required: false,
|
||||
default: 'issue',
|
||||
},
|
||||
canAttachFile: {
|
||||
type: Boolean,
|
||||
required: false,
|
||||
default: true,
|
||||
},
|
||||
updateEndpoint: {
|
||||
required: true,
|
||||
type: String,
|
||||
},
|
||||
data() {
|
||||
const store = new Store({
|
||||
titleHtml: this.initialTitleHtml,
|
||||
titleText: this.initialTitleText,
|
||||
descriptionHtml: this.initialDescriptionHtml,
|
||||
descriptionText: this.initialDescriptionText,
|
||||
updatedAt: this.updatedAt,
|
||||
updatedByName: this.updatedByName,
|
||||
updatedByPath: this.updatedByPath,
|
||||
taskStatus: this.initialTaskStatus,
|
||||
});
|
||||
canUpdate: {
|
||||
required: true,
|
||||
type: Boolean,
|
||||
},
|
||||
canDestroy: {
|
||||
required: true,
|
||||
type: Boolean,
|
||||
},
|
||||
showInlineEditButton: {
|
||||
type: Boolean,
|
||||
required: false,
|
||||
default: true,
|
||||
},
|
||||
showDeleteButton: {
|
||||
type: Boolean,
|
||||
required: false,
|
||||
default: true,
|
||||
},
|
||||
enableAutocomplete: {
|
||||
type: Boolean,
|
||||
required: false,
|
||||
default: true,
|
||||
},
|
||||
issuableRef: {
|
||||
type: String,
|
||||
required: true,
|
||||
},
|
||||
initialTitleHtml: {
|
||||
type: String,
|
||||
required: true,
|
||||
},
|
||||
initialTitleText: {
|
||||
type: String,
|
||||
required: true,
|
||||
},
|
||||
initialDescriptionHtml: {
|
||||
type: String,
|
||||
required: false,
|
||||
default: '',
|
||||
},
|
||||
initialDescriptionText: {
|
||||
type: String,
|
||||
required: false,
|
||||
default: '',
|
||||
},
|
||||
initialTaskStatus: {
|
||||
type: String,
|
||||
required: false,
|
||||
default: '',
|
||||
},
|
||||
updatedAt: {
|
||||
type: String,
|
||||
required: false,
|
||||
default: '',
|
||||
},
|
||||
updatedByName: {
|
||||
type: String,
|
||||
required: false,
|
||||
default: '',
|
||||
},
|
||||
updatedByPath: {
|
||||
type: String,
|
||||
required: false,
|
||||
default: '',
|
||||
},
|
||||
issuableTemplates: {
|
||||
type: Array,
|
||||
required: false,
|
||||
default: () => [],
|
||||
},
|
||||
markdownPreviewPath: {
|
||||
type: String,
|
||||
required: true,
|
||||
},
|
||||
markdownDocsPath: {
|
||||
type: String,
|
||||
required: true,
|
||||
},
|
||||
markdownVersion: {
|
||||
type: Number,
|
||||
required: false,
|
||||
default: 0,
|
||||
},
|
||||
projectPath: {
|
||||
type: String,
|
||||
required: true,
|
||||
},
|
||||
projectNamespace: {
|
||||
type: String,
|
||||
required: true,
|
||||
},
|
||||
issuableType: {
|
||||
type: String,
|
||||
required: false,
|
||||
default: 'issue',
|
||||
},
|
||||
canAttachFile: {
|
||||
type: Boolean,
|
||||
required: false,
|
||||
default: true,
|
||||
},
|
||||
},
|
||||
data() {
|
||||
const store = new Store({
|
||||
titleHtml: this.initialTitleHtml,
|
||||
titleText: this.initialTitleText,
|
||||
descriptionHtml: this.initialDescriptionHtml,
|
||||
descriptionText: this.initialDescriptionText,
|
||||
updatedAt: this.updatedAt,
|
||||
updatedByName: this.updatedByName,
|
||||
updatedByPath: this.updatedByPath,
|
||||
taskStatus: this.initialTaskStatus,
|
||||
});
|
||||
|
||||
return {
|
||||
store,
|
||||
state: store.state,
|
||||
showForm: false,
|
||||
};
|
||||
return {
|
||||
store,
|
||||
state: store.state,
|
||||
showForm: false,
|
||||
};
|
||||
},
|
||||
computed: {
|
||||
formState() {
|
||||
return this.store.formState;
|
||||
},
|
||||
computed: {
|
||||
formState() {
|
||||
return this.store.formState;
|
||||
},
|
||||
hasUpdated() {
|
||||
return !!this.state.updatedAt;
|
||||
},
|
||||
issueChanged() {
|
||||
const descriptionChanged =
|
||||
this.initialDescriptionText !== this.store.formState.description;
|
||||
const titleChanged =
|
||||
this.initialTitleText !== this.store.formState.title;
|
||||
return descriptionChanged || titleChanged;
|
||||
},
|
||||
hasUpdated() {
|
||||
return !!this.state.updatedAt;
|
||||
},
|
||||
created() {
|
||||
this.service = new Service(this.endpoint);
|
||||
this.poll = new Poll({
|
||||
resource: this.service,
|
||||
method: 'getData',
|
||||
successCallback: res => this.store.updateState(res.data),
|
||||
errorCallback(err) {
|
||||
throw new Error(err);
|
||||
},
|
||||
});
|
||||
issueChanged() {
|
||||
const descriptionChanged = this.initialDescriptionText !== this.store.formState.description;
|
||||
const titleChanged = this.initialTitleText !== this.store.formState.title;
|
||||
return descriptionChanged || titleChanged;
|
||||
},
|
||||
},
|
||||
created() {
|
||||
this.service = new Service(this.endpoint);
|
||||
this.poll = new Poll({
|
||||
resource: this.service,
|
||||
method: 'getData',
|
||||
successCallback: res => this.store.updateState(res.data),
|
||||
errorCallback(err) {
|
||||
throw new Error(err);
|
||||
},
|
||||
});
|
||||
|
||||
if (!Visibility.hidden()) {
|
||||
this.poll.makeRequest();
|
||||
}
|
||||
|
||||
Visibility.change(() => {
|
||||
if (!Visibility.hidden()) {
|
||||
this.poll.makeRequest();
|
||||
this.poll.restart();
|
||||
} else {
|
||||
this.poll.stop();
|
||||
}
|
||||
});
|
||||
|
||||
Visibility.change(() => {
|
||||
if (!Visibility.hidden()) {
|
||||
this.poll.restart();
|
||||
} else {
|
||||
this.poll.stop();
|
||||
}
|
||||
});
|
||||
window.addEventListener('beforeunload', this.handleBeforeUnloadEvent);
|
||||
|
||||
window.addEventListener('beforeunload', this.handleBeforeUnloadEvent);
|
||||
|
||||
eventHub.$on('delete.issuable', this.deleteIssuable);
|
||||
eventHub.$on('update.issuable', this.updateIssuable);
|
||||
eventHub.$on('close.form', this.closeForm);
|
||||
eventHub.$on('open.form', this.openForm);
|
||||
eventHub.$on('delete.issuable', this.deleteIssuable);
|
||||
eventHub.$on('update.issuable', this.updateIssuable);
|
||||
eventHub.$on('close.form', this.closeForm);
|
||||
eventHub.$on('open.form', this.openForm);
|
||||
},
|
||||
beforeDestroy() {
|
||||
eventHub.$off('delete.issuable', this.deleteIssuable);
|
||||
eventHub.$off('update.issuable', this.updateIssuable);
|
||||
eventHub.$off('close.form', this.closeForm);
|
||||
eventHub.$off('open.form', this.openForm);
|
||||
window.removeEventListener('beforeunload', this.handleBeforeUnloadEvent);
|
||||
},
|
||||
methods: {
|
||||
handleBeforeUnloadEvent(e) {
|
||||
const event = e;
|
||||
if (this.showForm && this.issueChanged) {
|
||||
event.returnValue = 'Are you sure you want to lose your issue information?';
|
||||
}
|
||||
return undefined;
|
||||
},
|
||||
beforeDestroy() {
|
||||
eventHub.$off('delete.issuable', this.deleteIssuable);
|
||||
eventHub.$off('update.issuable', this.updateIssuable);
|
||||
eventHub.$off('close.form', this.closeForm);
|
||||
eventHub.$off('open.form', this.openForm);
|
||||
window.removeEventListener('beforeunload', this.handleBeforeUnloadEvent);
|
||||
},
|
||||
methods: {
|
||||
handleBeforeUnloadEvent(e) {
|
||||
const event = e;
|
||||
if (this.showForm && this.issueChanged) {
|
||||
event.returnValue = 'Are you sure you want to lose your issue information?';
|
||||
}
|
||||
return undefined;
|
||||
},
|
||||
|
||||
openForm() {
|
||||
if (!this.showForm) {
|
||||
this.showForm = true;
|
||||
this.store.setFormState({
|
||||
title: this.state.titleText,
|
||||
description: this.state.descriptionText,
|
||||
lockedWarningVisible: false,
|
||||
updateLoading: false,
|
||||
});
|
||||
}
|
||||
},
|
||||
closeForm() {
|
||||
this.showForm = false;
|
||||
},
|
||||
|
||||
updateIssuable() {
|
||||
return this.service.updateIssuable(this.store.formState)
|
||||
.then(res => res.data)
|
||||
.then(data => this.checkForSpam(data))
|
||||
.then((data) => {
|
||||
if (window.location.pathname !== data.web_url) {
|
||||
visitUrl(data.web_url);
|
||||
}
|
||||
|
||||
return this.service.getData();
|
||||
})
|
||||
.then(res => res.data)
|
||||
.then((data) => {
|
||||
this.store.updateState(data);
|
||||
eventHub.$emit('close.form');
|
||||
})
|
||||
.catch((error) => {
|
||||
if (error && error.name === 'SpamError') {
|
||||
this.openRecaptcha();
|
||||
} else {
|
||||
eventHub.$emit('close.form');
|
||||
window.Flash(`Error updating ${this.issuableType}`);
|
||||
}
|
||||
});
|
||||
},
|
||||
|
||||
closeRecaptchaModal() {
|
||||
openForm() {
|
||||
if (!this.showForm) {
|
||||
this.showForm = true;
|
||||
this.store.setFormState({
|
||||
title: this.state.titleText,
|
||||
description: this.state.descriptionText,
|
||||
lockedWarningVisible: false,
|
||||
updateLoading: false,
|
||||
});
|
||||
|
||||
this.closeRecaptcha();
|
||||
},
|
||||
|
||||
deleteIssuable() {
|
||||
this.service.deleteIssuable()
|
||||
.then(res => res.data)
|
||||
.then((data) => {
|
||||
// Stop the poll so we don't get 404's with the issuable not existing
|
||||
this.poll.stop();
|
||||
|
||||
visitUrl(data.web_url);
|
||||
})
|
||||
.catch(() => {
|
||||
eventHub.$emit('close.form');
|
||||
window.Flash(`Error deleting ${this.issuableType}`);
|
||||
});
|
||||
},
|
||||
}
|
||||
},
|
||||
};
|
||||
closeForm() {
|
||||
this.showForm = false;
|
||||
},
|
||||
|
||||
updateIssuable() {
|
||||
return this.service
|
||||
.updateIssuable(this.store.formState)
|
||||
.then(res => res.data)
|
||||
.then(data => this.checkForSpam(data))
|
||||
.then(data => {
|
||||
if (window.location.pathname !== data.web_url) {
|
||||
visitUrl(data.web_url);
|
||||
}
|
||||
|
||||
return this.service.getData();
|
||||
})
|
||||
.then(res => res.data)
|
||||
.then(data => {
|
||||
this.store.updateState(data);
|
||||
eventHub.$emit('close.form');
|
||||
})
|
||||
.catch(error => {
|
||||
if (error && error.name === 'SpamError') {
|
||||
this.openRecaptcha();
|
||||
} else {
|
||||
eventHub.$emit('close.form');
|
||||
window.Flash(`Error updating ${this.issuableType}`);
|
||||
}
|
||||
});
|
||||
},
|
||||
|
||||
closeRecaptchaModal() {
|
||||
this.store.setFormState({
|
||||
updateLoading: false,
|
||||
});
|
||||
|
||||
this.closeRecaptcha();
|
||||
},
|
||||
|
||||
deleteIssuable() {
|
||||
this.service
|
||||
.deleteIssuable()
|
||||
.then(res => res.data)
|
||||
.then(data => {
|
||||
// Stop the poll so we don't get 404's with the issuable not existing
|
||||
this.poll.stop();
|
||||
|
||||
visitUrl(data.web_url);
|
||||
})
|
||||
.catch(() => {
|
||||
eventHub.$emit('close.form');
|
||||
window.Flash(`Error deleting ${this.issuableType}`);
|
||||
});
|
||||
},
|
||||
},
|
||||
};
|
||||
</script>
|
||||
|
||||
<template>
|
||||
|
|
|
@ -1,110 +1,105 @@
|
|||
<script>
|
||||
import $ from 'jquery';
|
||||
import animateMixin from '../mixins/animate';
|
||||
import TaskList from '../../task_list';
|
||||
import recaptchaModalImplementor from '../../vue_shared/mixins/recaptcha_modal_implementor';
|
||||
import $ from 'jquery';
|
||||
import animateMixin from '../mixins/animate';
|
||||
import TaskList from '../../task_list';
|
||||
import recaptchaModalImplementor from '../../vue_shared/mixins/recaptcha_modal_implementor';
|
||||
|
||||
export default {
|
||||
mixins: [
|
||||
animateMixin,
|
||||
recaptchaModalImplementor,
|
||||
],
|
||||
export default {
|
||||
mixins: [animateMixin, recaptchaModalImplementor],
|
||||
|
||||
props: {
|
||||
canUpdate: {
|
||||
type: Boolean,
|
||||
required: true,
|
||||
},
|
||||
descriptionHtml: {
|
||||
type: String,
|
||||
required: true,
|
||||
},
|
||||
descriptionText: {
|
||||
type: String,
|
||||
required: true,
|
||||
},
|
||||
taskStatus: {
|
||||
type: String,
|
||||
required: false,
|
||||
default: '',
|
||||
},
|
||||
issuableType: {
|
||||
type: String,
|
||||
required: false,
|
||||
default: 'issue',
|
||||
},
|
||||
updateUrl: {
|
||||
type: String,
|
||||
required: false,
|
||||
default: null,
|
||||
},
|
||||
props: {
|
||||
canUpdate: {
|
||||
type: Boolean,
|
||||
required: true,
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
preAnimation: false,
|
||||
pulseAnimation: false,
|
||||
};
|
||||
descriptionHtml: {
|
||||
type: String,
|
||||
required: true,
|
||||
},
|
||||
watch: {
|
||||
descriptionHtml() {
|
||||
this.animateChange();
|
||||
descriptionText: {
|
||||
type: String,
|
||||
required: true,
|
||||
},
|
||||
taskStatus: {
|
||||
type: String,
|
||||
required: false,
|
||||
default: '',
|
||||
},
|
||||
issuableType: {
|
||||
type: String,
|
||||
required: false,
|
||||
default: 'issue',
|
||||
},
|
||||
updateUrl: {
|
||||
type: String,
|
||||
required: false,
|
||||
default: null,
|
||||
},
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
preAnimation: false,
|
||||
pulseAnimation: false,
|
||||
};
|
||||
},
|
||||
watch: {
|
||||
descriptionHtml() {
|
||||
this.animateChange();
|
||||
|
||||
this.$nextTick(() => {
|
||||
this.renderGFM();
|
||||
});
|
||||
},
|
||||
taskStatus() {
|
||||
this.updateTaskStatusText();
|
||||
},
|
||||
this.$nextTick(() => {
|
||||
this.renderGFM();
|
||||
});
|
||||
},
|
||||
mounted() {
|
||||
this.renderGFM();
|
||||
taskStatus() {
|
||||
this.updateTaskStatusText();
|
||||
},
|
||||
methods: {
|
||||
renderGFM() {
|
||||
$(this.$refs['gfm-content']).renderGFM();
|
||||
},
|
||||
mounted() {
|
||||
this.renderGFM();
|
||||
this.updateTaskStatusText();
|
||||
},
|
||||
methods: {
|
||||
renderGFM() {
|
||||
$(this.$refs['gfm-content']).renderGFM();
|
||||
|
||||
if (this.canUpdate) {
|
||||
// eslint-disable-next-line no-new
|
||||
new TaskList({
|
||||
dataType: this.issuableType,
|
||||
fieldName: 'description',
|
||||
selector: '.detail-page-description',
|
||||
onSuccess: this.taskListUpdateSuccess.bind(this),
|
||||
});
|
||||
}
|
||||
},
|
||||
|
||||
taskListUpdateSuccess(data) {
|
||||
try {
|
||||
this.checkForSpam(data);
|
||||
this.closeRecaptcha();
|
||||
} catch (error) {
|
||||
if (error && error.name === 'SpamError') this.openRecaptcha();
|
||||
}
|
||||
},
|
||||
|
||||
updateTaskStatusText() {
|
||||
const taskRegexMatches = this.taskStatus.match(/(\d+) of ((?!0)\d+)/);
|
||||
const $issuableHeader = $('.issuable-meta');
|
||||
const $tasks = $('#task_status', $issuableHeader);
|
||||
const $tasksShort = $('#task_status_short', $issuableHeader);
|
||||
|
||||
if (taskRegexMatches) {
|
||||
$tasks.text(this.taskStatus);
|
||||
$tasksShort.text(
|
||||
`${taskRegexMatches[1]}/${taskRegexMatches[2]} task${taskRegexMatches[2] > 1 ?
|
||||
's' :
|
||||
''}`,
|
||||
);
|
||||
} else {
|
||||
$tasks.text('');
|
||||
$tasksShort.text('');
|
||||
}
|
||||
},
|
||||
if (this.canUpdate) {
|
||||
// eslint-disable-next-line no-new
|
||||
new TaskList({
|
||||
dataType: this.issuableType,
|
||||
fieldName: 'description',
|
||||
selector: '.detail-page-description',
|
||||
onSuccess: this.taskListUpdateSuccess.bind(this),
|
||||
});
|
||||
}
|
||||
},
|
||||
};
|
||||
|
||||
taskListUpdateSuccess(data) {
|
||||
try {
|
||||
this.checkForSpam(data);
|
||||
this.closeRecaptcha();
|
||||
} catch (error) {
|
||||
if (error && error.name === 'SpamError') this.openRecaptcha();
|
||||
}
|
||||
},
|
||||
|
||||
updateTaskStatusText() {
|
||||
const taskRegexMatches = this.taskStatus.match(/(\d+) of ((?!0)\d+)/);
|
||||
const $issuableHeader = $('.issuable-meta');
|
||||
const $tasks = $('#task_status', $issuableHeader);
|
||||
const $tasksShort = $('#task_status_short', $issuableHeader);
|
||||
|
||||
if (taskRegexMatches) {
|
||||
$tasks.text(this.taskStatus);
|
||||
$tasksShort.text(
|
||||
`${taskRegexMatches[1]}/${taskRegexMatches[2]} task${taskRegexMatches[2] > 1 ? 's' : ''}`,
|
||||
);
|
||||
} else {
|
||||
$tasks.text('');
|
||||
$tasksShort.text('');
|
||||
}
|
||||
},
|
||||
},
|
||||
};
|
||||
</script>
|
||||
|
||||
<template>
|
||||
|
|
|
@ -1,64 +1,64 @@
|
|||
<script>
|
||||
import { __, sprintf } from '~/locale';
|
||||
import updateMixin from '../mixins/update';
|
||||
import eventHub from '../event_hub';
|
||||
import { __, sprintf } from '~/locale';
|
||||
import updateMixin from '../mixins/update';
|
||||
import eventHub from '../event_hub';
|
||||
|
||||
const issuableTypes = {
|
||||
issue: __('Issue'),
|
||||
epic: __('Epic'),
|
||||
};
|
||||
const issuableTypes = {
|
||||
issue: __('Issue'),
|
||||
epic: __('Epic'),
|
||||
};
|
||||
|
||||
export default {
|
||||
mixins: [updateMixin],
|
||||
props: {
|
||||
canDestroy: {
|
||||
type: Boolean,
|
||||
required: true,
|
||||
},
|
||||
formState: {
|
||||
type: Object,
|
||||
required: true,
|
||||
},
|
||||
showDeleteButton: {
|
||||
type: Boolean,
|
||||
required: false,
|
||||
default: true,
|
||||
},
|
||||
issuableType: {
|
||||
type: String,
|
||||
required: true,
|
||||
},
|
||||
export default {
|
||||
mixins: [updateMixin],
|
||||
props: {
|
||||
canDestroy: {
|
||||
type: Boolean,
|
||||
required: true,
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
deleteLoading: false,
|
||||
};
|
||||
formState: {
|
||||
type: Object,
|
||||
required: true,
|
||||
},
|
||||
computed: {
|
||||
isSubmitEnabled() {
|
||||
return this.formState.title.trim() !== '';
|
||||
},
|
||||
shouldShowDeleteButton() {
|
||||
return this.canDestroy && this.showDeleteButton;
|
||||
},
|
||||
showDeleteButton: {
|
||||
type: Boolean,
|
||||
required: false,
|
||||
default: true,
|
||||
},
|
||||
methods: {
|
||||
closeForm() {
|
||||
eventHub.$emit('close.form');
|
||||
},
|
||||
deleteIssuable() {
|
||||
const confirmMessage = sprintf(__('%{issuableType} will be removed! Are you sure?'), {
|
||||
issuableType: issuableTypes[this.issuableType],
|
||||
});
|
||||
// eslint-disable-next-line no-alert
|
||||
if (window.confirm(confirmMessage)) {
|
||||
this.deleteLoading = true;
|
||||
issuableType: {
|
||||
type: String,
|
||||
required: true,
|
||||
},
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
deleteLoading: false,
|
||||
};
|
||||
},
|
||||
computed: {
|
||||
isSubmitEnabled() {
|
||||
return this.formState.title.trim() !== '';
|
||||
},
|
||||
shouldShowDeleteButton() {
|
||||
return this.canDestroy && this.showDeleteButton;
|
||||
},
|
||||
},
|
||||
methods: {
|
||||
closeForm() {
|
||||
eventHub.$emit('close.form');
|
||||
},
|
||||
deleteIssuable() {
|
||||
const confirmMessage = sprintf(__('%{issuableType} will be removed! Are you sure?'), {
|
||||
issuableType: issuableTypes[this.issuableType],
|
||||
});
|
||||
// eslint-disable-next-line no-alert
|
||||
if (window.confirm(confirmMessage)) {
|
||||
this.deleteLoading = true;
|
||||
|
||||
eventHub.$emit('delete.issuable');
|
||||
}
|
||||
},
|
||||
eventHub.$emit('delete.issuable');
|
||||
}
|
||||
},
|
||||
};
|
||||
},
|
||||
};
|
||||
</script>
|
||||
|
||||
<template>
|
||||
|
|
|
@ -1,33 +1,33 @@
|
|||
<script>
|
||||
import timeAgoTooltip from '../../vue_shared/components/time_ago_tooltip.vue';
|
||||
import timeAgoTooltip from '../../vue_shared/components/time_ago_tooltip.vue';
|
||||
|
||||
export default {
|
||||
components: {
|
||||
timeAgoTooltip,
|
||||
export default {
|
||||
components: {
|
||||
timeAgoTooltip,
|
||||
},
|
||||
props: {
|
||||
updatedAt: {
|
||||
type: String,
|
||||
required: false,
|
||||
default: '',
|
||||
},
|
||||
props: {
|
||||
updatedAt: {
|
||||
type: String,
|
||||
required: false,
|
||||
default: '',
|
||||
},
|
||||
updatedByName: {
|
||||
type: String,
|
||||
required: false,
|
||||
default: '',
|
||||
},
|
||||
updatedByPath: {
|
||||
type: String,
|
||||
required: false,
|
||||
default: '',
|
||||
},
|
||||
updatedByName: {
|
||||
type: String,
|
||||
required: false,
|
||||
default: '',
|
||||
},
|
||||
computed: {
|
||||
hasUpdatedBy() {
|
||||
return this.updatedByName && this.updatedByPath;
|
||||
},
|
||||
updatedByPath: {
|
||||
type: String,
|
||||
required: false,
|
||||
default: '',
|
||||
},
|
||||
};
|
||||
},
|
||||
computed: {
|
||||
hasUpdatedBy() {
|
||||
return this.updatedByName && this.updatedByPath;
|
||||
},
|
||||
},
|
||||
};
|
||||
</script>
|
||||
|
||||
<template>
|
||||
|
@ -53,4 +53,3 @@
|
|||
</span>
|
||||
</small>
|
||||
</template>
|
||||
|
||||
|
|
|
@ -1,45 +1,45 @@
|
|||
<script>
|
||||
import updateMixin from '../../mixins/update';
|
||||
import markdownField from '../../../vue_shared/components/markdown/field.vue';
|
||||
import updateMixin from '../../mixins/update';
|
||||
import markdownField from '../../../vue_shared/components/markdown/field.vue';
|
||||
|
||||
export default {
|
||||
components: {
|
||||
markdownField,
|
||||
export default {
|
||||
components: {
|
||||
markdownField,
|
||||
},
|
||||
mixins: [updateMixin],
|
||||
props: {
|
||||
formState: {
|
||||
type: Object,
|
||||
required: true,
|
||||
},
|
||||
mixins: [updateMixin],
|
||||
props: {
|
||||
formState: {
|
||||
type: Object,
|
||||
required: true,
|
||||
},
|
||||
markdownPreviewPath: {
|
||||
type: String,
|
||||
required: true,
|
||||
},
|
||||
markdownDocsPath: {
|
||||
type: String,
|
||||
required: true,
|
||||
},
|
||||
markdownVersion: {
|
||||
type: Number,
|
||||
required: false,
|
||||
default: 0,
|
||||
},
|
||||
canAttachFile: {
|
||||
type: Boolean,
|
||||
required: false,
|
||||
default: true,
|
||||
},
|
||||
enableAutocomplete: {
|
||||
type: Boolean,
|
||||
required: false,
|
||||
default: true,
|
||||
},
|
||||
markdownPreviewPath: {
|
||||
type: String,
|
||||
required: true,
|
||||
},
|
||||
mounted() {
|
||||
this.$refs.textarea.focus();
|
||||
markdownDocsPath: {
|
||||
type: String,
|
||||
required: true,
|
||||
},
|
||||
};
|
||||
markdownVersion: {
|
||||
type: Number,
|
||||
required: false,
|
||||
default: 0,
|
||||
},
|
||||
canAttachFile: {
|
||||
type: Boolean,
|
||||
required: false,
|
||||
default: true,
|
||||
},
|
||||
enableAutocomplete: {
|
||||
type: Boolean,
|
||||
required: false,
|
||||
default: true,
|
||||
},
|
||||
},
|
||||
mounted() {
|
||||
this.$refs.textarea.focus();
|
||||
},
|
||||
};
|
||||
</script>
|
||||
|
||||
<template>
|
||||
|
|
|
@ -1,46 +1,46 @@
|
|||
<script>
|
||||
import $ from 'jquery';
|
||||
import IssuableTemplateSelectors from '../../../templates/issuable_template_selectors';
|
||||
import $ from 'jquery';
|
||||
import IssuableTemplateSelectors from '../../../templates/issuable_template_selectors';
|
||||
|
||||
export default {
|
||||
props: {
|
||||
formState: {
|
||||
type: Object,
|
||||
required: true,
|
||||
},
|
||||
issuableTemplates: {
|
||||
type: Array,
|
||||
required: false,
|
||||
default: () => [],
|
||||
},
|
||||
projectPath: {
|
||||
type: String,
|
||||
required: true,
|
||||
},
|
||||
projectNamespace: {
|
||||
type: String,
|
||||
required: true,
|
||||
},
|
||||
export default {
|
||||
props: {
|
||||
formState: {
|
||||
type: Object,
|
||||
required: true,
|
||||
},
|
||||
computed: {
|
||||
issuableTemplatesJson() {
|
||||
return JSON.stringify(this.issuableTemplates);
|
||||
},
|
||||
issuableTemplates: {
|
||||
type: Array,
|
||||
required: false,
|
||||
default: () => [],
|
||||
},
|
||||
mounted() {
|
||||
// Create the editor for the template
|
||||
const editor = document.querySelector('.detail-page-description .note-textarea') || {};
|
||||
editor.setValue = (val) => {
|
||||
this.formState.description = val;
|
||||
};
|
||||
editor.getValue = () => this.formState.description;
|
||||
projectPath: {
|
||||
type: String,
|
||||
required: true,
|
||||
},
|
||||
projectNamespace: {
|
||||
type: String,
|
||||
required: true,
|
||||
},
|
||||
},
|
||||
computed: {
|
||||
issuableTemplatesJson() {
|
||||
return JSON.stringify(this.issuableTemplates);
|
||||
},
|
||||
},
|
||||
mounted() {
|
||||
// Create the editor for the template
|
||||
const editor = document.querySelector('.detail-page-description .note-textarea') || {};
|
||||
editor.setValue = val => {
|
||||
this.formState.description = val;
|
||||
};
|
||||
editor.getValue = () => this.formState.description;
|
||||
|
||||
this.issuableTemplate = new IssuableTemplateSelectors({
|
||||
$dropdowns: $(this.$refs.toggle),
|
||||
editor,
|
||||
});
|
||||
},
|
||||
};
|
||||
this.issuableTemplate = new IssuableTemplateSelectors({
|
||||
$dropdowns: $(this.$refs.toggle),
|
||||
editor,
|
||||
});
|
||||
},
|
||||
};
|
||||
</script>
|
||||
|
||||
<template>
|
||||
|
|
|
@ -1,15 +1,15 @@
|
|||
<script>
|
||||
import updateMixin from '../../mixins/update';
|
||||
import updateMixin from '../../mixins/update';
|
||||
|
||||
export default {
|
||||
mixins: [updateMixin],
|
||||
props: {
|
||||
formState: {
|
||||
type: Object,
|
||||
required: true,
|
||||
},
|
||||
export default {
|
||||
mixins: [updateMixin],
|
||||
props: {
|
||||
formState: {
|
||||
type: Object,
|
||||
required: true,
|
||||
},
|
||||
};
|
||||
},
|
||||
};
|
||||
</script>
|
||||
|
||||
<template>
|
||||
|
|
|
@ -1,79 +1,79 @@
|
|||
<script>
|
||||
import lockedWarning from './locked_warning.vue';
|
||||
import titleField from './fields/title.vue';
|
||||
import descriptionField from './fields/description.vue';
|
||||
import editActions from './edit_actions.vue';
|
||||
import descriptionTemplate from './fields/description_template.vue';
|
||||
import lockedWarning from './locked_warning.vue';
|
||||
import titleField from './fields/title.vue';
|
||||
import descriptionField from './fields/description.vue';
|
||||
import editActions from './edit_actions.vue';
|
||||
import descriptionTemplate from './fields/description_template.vue';
|
||||
|
||||
export default {
|
||||
components: {
|
||||
lockedWarning,
|
||||
titleField,
|
||||
descriptionField,
|
||||
descriptionTemplate,
|
||||
editActions,
|
||||
export default {
|
||||
components: {
|
||||
lockedWarning,
|
||||
titleField,
|
||||
descriptionField,
|
||||
descriptionTemplate,
|
||||
editActions,
|
||||
},
|
||||
props: {
|
||||
canDestroy: {
|
||||
type: Boolean,
|
||||
required: true,
|
||||
},
|
||||
props: {
|
||||
canDestroy: {
|
||||
type: Boolean,
|
||||
required: true,
|
||||
},
|
||||
formState: {
|
||||
type: Object,
|
||||
required: true,
|
||||
},
|
||||
issuableTemplates: {
|
||||
type: Array,
|
||||
required: false,
|
||||
default: () => [],
|
||||
},
|
||||
issuableType: {
|
||||
type: String,
|
||||
required: true,
|
||||
},
|
||||
markdownPreviewPath: {
|
||||
type: String,
|
||||
required: true,
|
||||
},
|
||||
markdownDocsPath: {
|
||||
type: String,
|
||||
required: true,
|
||||
},
|
||||
markdownVersion: {
|
||||
type: Number,
|
||||
required: false,
|
||||
default: 0,
|
||||
},
|
||||
projectPath: {
|
||||
type: String,
|
||||
required: true,
|
||||
},
|
||||
projectNamespace: {
|
||||
type: String,
|
||||
required: true,
|
||||
},
|
||||
showDeleteButton: {
|
||||
type: Boolean,
|
||||
required: false,
|
||||
default: true,
|
||||
},
|
||||
canAttachFile: {
|
||||
type: Boolean,
|
||||
required: false,
|
||||
default: true,
|
||||
},
|
||||
enableAutocomplete: {
|
||||
type: Boolean,
|
||||
required: false,
|
||||
default: true,
|
||||
},
|
||||
formState: {
|
||||
type: Object,
|
||||
required: true,
|
||||
},
|
||||
computed: {
|
||||
hasIssuableTemplates() {
|
||||
return this.issuableTemplates.length;
|
||||
},
|
||||
issuableTemplates: {
|
||||
type: Array,
|
||||
required: false,
|
||||
default: () => [],
|
||||
},
|
||||
};
|
||||
issuableType: {
|
||||
type: String,
|
||||
required: true,
|
||||
},
|
||||
markdownPreviewPath: {
|
||||
type: String,
|
||||
required: true,
|
||||
},
|
||||
markdownDocsPath: {
|
||||
type: String,
|
||||
required: true,
|
||||
},
|
||||
markdownVersion: {
|
||||
type: Number,
|
||||
required: false,
|
||||
default: 0,
|
||||
},
|
||||
projectPath: {
|
||||
type: String,
|
||||
required: true,
|
||||
},
|
||||
projectNamespace: {
|
||||
type: String,
|
||||
required: true,
|
||||
},
|
||||
showDeleteButton: {
|
||||
type: Boolean,
|
||||
required: false,
|
||||
default: true,
|
||||
},
|
||||
canAttachFile: {
|
||||
type: Boolean,
|
||||
required: false,
|
||||
default: true,
|
||||
},
|
||||
enableAutocomplete: {
|
||||
type: Boolean,
|
||||
required: false,
|
||||
default: true,
|
||||
},
|
||||
},
|
||||
computed: {
|
||||
hasIssuableTemplates() {
|
||||
return this.issuableTemplates.length;
|
||||
},
|
||||
},
|
||||
};
|
||||
</script>
|
||||
|
||||
<template>
|
||||
|
|
|
@ -1,11 +1,11 @@
|
|||
<script>
|
||||
export default {
|
||||
computed: {
|
||||
currentPath() {
|
||||
return window.location.pathname;
|
||||
},
|
||||
export default {
|
||||
computed: {
|
||||
currentPath() {
|
||||
return window.location.pathname;
|
||||
},
|
||||
};
|
||||
},
|
||||
};
|
||||
</script>
|
||||
|
||||
<template>
|
||||
|
|
|
@ -25,8 +25,10 @@ export default class Store {
|
|||
}
|
||||
|
||||
stateShouldUpdate(data) {
|
||||
return this.state.titleText !== data.title_text ||
|
||||
this.state.descriptionText !== data.description_text;
|
||||
return (
|
||||
this.state.titleText !== data.title_text ||
|
||||
this.state.descriptionText !== data.description_text
|
||||
);
|
||||
}
|
||||
|
||||
setFormState(state) {
|
||||
|
|
|
@ -1,30 +1,28 @@
|
|||
<script>
|
||||
import TimeagoTooltip from '~/vue_shared/components/time_ago_tooltip.vue';
|
||||
import timeagoMixin from '~/vue_shared/mixins/timeago';
|
||||
import TimeagoTooltip from '~/vue_shared/components/time_ago_tooltip.vue';
|
||||
import timeagoMixin from '~/vue_shared/mixins/timeago';
|
||||
|
||||
export default {
|
||||
components: {
|
||||
TimeagoTooltip,
|
||||
export default {
|
||||
components: {
|
||||
TimeagoTooltip,
|
||||
},
|
||||
mixins: [timeagoMixin],
|
||||
props: {
|
||||
artifact: {
|
||||
type: Object,
|
||||
required: true,
|
||||
},
|
||||
mixins: [
|
||||
timeagoMixin,
|
||||
],
|
||||
props: {
|
||||
artifact: {
|
||||
type: Object,
|
||||
required: true,
|
||||
},
|
||||
},
|
||||
computed: {
|
||||
isExpired() {
|
||||
return this.artifact.expired;
|
||||
},
|
||||
computed: {
|
||||
isExpired() {
|
||||
return this.artifact.expired;
|
||||
},
|
||||
// Only when the key is `false` we can render this block
|
||||
willExpire() {
|
||||
return this.artifact.expired === false;
|
||||
},
|
||||
// Only when the key is `false` we can render this block
|
||||
willExpire() {
|
||||
return this.artifact.expired === false;
|
||||
},
|
||||
};
|
||||
},
|
||||
};
|
||||
</script>
|
||||
<template>
|
||||
<div class="block">
|
||||
|
|
|
@ -1,26 +1,26 @@
|
|||
<script>
|
||||
import ClipboardButton from '~/vue_shared/components/clipboard_button.vue';
|
||||
import ClipboardButton from '~/vue_shared/components/clipboard_button.vue';
|
||||
|
||||
export default {
|
||||
components: {
|
||||
ClipboardButton,
|
||||
export default {
|
||||
components: {
|
||||
ClipboardButton,
|
||||
},
|
||||
props: {
|
||||
commit: {
|
||||
type: Object,
|
||||
required: true,
|
||||
},
|
||||
props: {
|
||||
commit: {
|
||||
type: Object,
|
||||
required: true,
|
||||
},
|
||||
mergeRequest: {
|
||||
type: Object,
|
||||
required: false,
|
||||
default: null,
|
||||
},
|
||||
isLastBlock: {
|
||||
type: Boolean,
|
||||
required: true,
|
||||
},
|
||||
mergeRequest: {
|
||||
type: Object,
|
||||
required: false,
|
||||
default: null,
|
||||
},
|
||||
};
|
||||
isLastBlock: {
|
||||
type: Boolean,
|
||||
required: true,
|
||||
},
|
||||
},
|
||||
};
|
||||
</script>
|
||||
<template>
|
||||
<div
|
||||
|
|
|
@ -1,38 +1,38 @@
|
|||
<script>
|
||||
export default {
|
||||
props: {
|
||||
illustrationPath: {
|
||||
type: String,
|
||||
required: true,
|
||||
},
|
||||
illustrationSizeClass: {
|
||||
type: String,
|
||||
required: true,
|
||||
},
|
||||
title: {
|
||||
type: String,
|
||||
required: true,
|
||||
},
|
||||
content: {
|
||||
type: String,
|
||||
required: false,
|
||||
default: null,
|
||||
},
|
||||
action: {
|
||||
type: Object,
|
||||
required: false,
|
||||
default: null,
|
||||
validator(value) {
|
||||
return (
|
||||
value === null ||
|
||||
(Object.prototype.hasOwnProperty.call(value, 'path') &&
|
||||
Object.prototype.hasOwnProperty.call(value, 'method') &&
|
||||
Object.prototype.hasOwnProperty.call(value, 'button_title'))
|
||||
);
|
||||
},
|
||||
export default {
|
||||
props: {
|
||||
illustrationPath: {
|
||||
type: String,
|
||||
required: true,
|
||||
},
|
||||
illustrationSizeClass: {
|
||||
type: String,
|
||||
required: true,
|
||||
},
|
||||
title: {
|
||||
type: String,
|
||||
required: true,
|
||||
},
|
||||
content: {
|
||||
type: String,
|
||||
required: false,
|
||||
default: null,
|
||||
},
|
||||
action: {
|
||||
type: Object,
|
||||
required: false,
|
||||
default: null,
|
||||
validator(value) {
|
||||
return (
|
||||
value === null ||
|
||||
(Object.prototype.hasOwnProperty.call(value, 'path') &&
|
||||
Object.prototype.hasOwnProperty.call(value, 'method') &&
|
||||
Object.prototype.hasOwnProperty.call(value, 'button_title'))
|
||||
);
|
||||
},
|
||||
},
|
||||
};
|
||||
},
|
||||
};
|
||||
</script>
|
||||
<template>
|
||||
<div class="row empty-state">
|
||||
|
|
|
@ -1,129 +1,131 @@
|
|||
<script>
|
||||
import _ from 'underscore';
|
||||
import CiIcon from '~/vue_shared/components/ci_icon.vue';
|
||||
import { sprintf, __ } from '../../locale';
|
||||
import _ from 'underscore';
|
||||
import CiIcon from '~/vue_shared/components/ci_icon.vue';
|
||||
import { sprintf, __ } from '../../locale';
|
||||
|
||||
export default {
|
||||
components: {
|
||||
CiIcon,
|
||||
export default {
|
||||
components: {
|
||||
CiIcon,
|
||||
},
|
||||
props: {
|
||||
deploymentStatus: {
|
||||
type: Object,
|
||||
required: true,
|
||||
},
|
||||
props: {
|
||||
deploymentStatus: {
|
||||
type: Object,
|
||||
required: true,
|
||||
},
|
||||
iconStatus: {
|
||||
type: Object,
|
||||
required: true,
|
||||
},
|
||||
iconStatus: {
|
||||
type: Object,
|
||||
required: true,
|
||||
},
|
||||
computed: {
|
||||
environment() {
|
||||
let environmentText;
|
||||
switch (this.deploymentStatus.status) {
|
||||
case 'last':
|
||||
},
|
||||
computed: {
|
||||
environment() {
|
||||
let environmentText;
|
||||
switch (this.deploymentStatus.status) {
|
||||
case 'last':
|
||||
environmentText = sprintf(
|
||||
__('This job is the most recent deployment to %{link}.'),
|
||||
{ link: this.environmentLink },
|
||||
false,
|
||||
);
|
||||
break;
|
||||
case 'out_of_date':
|
||||
if (this.hasLastDeployment) {
|
||||
environmentText = sprintf(
|
||||
__('This job is the most recent deployment to %{link}.'),
|
||||
{ link: this.environmentLink },
|
||||
__(
|
||||
'This job is an out-of-date deployment to %{environmentLink}. View the most recent deployment %{deploymentLink}.',
|
||||
),
|
||||
{
|
||||
environmentLink: this.environmentLink,
|
||||
deploymentLink: this.deploymentLink(`#${this.lastDeployment.iid}`),
|
||||
},
|
||||
false,
|
||||
);
|
||||
break;
|
||||
case 'out_of_date':
|
||||
if (this.hasLastDeployment) {
|
||||
environmentText = sprintf(
|
||||
__(
|
||||
'This job is an out-of-date deployment to %{environmentLink}. View the most recent deployment %{deploymentLink}.',
|
||||
),
|
||||
{
|
||||
environmentLink: this.environmentLink,
|
||||
deploymentLink: this.deploymentLink(`#${this.lastDeployment.iid}`),
|
||||
},
|
||||
false,
|
||||
);
|
||||
} else {
|
||||
environmentText = sprintf(
|
||||
__('This job is an out-of-date deployment to %{environmentLink}.'),
|
||||
{ environmentLink: this.environmentLink },
|
||||
false,
|
||||
);
|
||||
}
|
||||
|
||||
break;
|
||||
case 'failed':
|
||||
} else {
|
||||
environmentText = sprintf(
|
||||
__('The deployment of this job to %{environmentLink} did not succeed.'),
|
||||
__('This job is an out-of-date deployment to %{environmentLink}.'),
|
||||
{ environmentLink: this.environmentLink },
|
||||
false,
|
||||
);
|
||||
break;
|
||||
case 'creating':
|
||||
if (this.hasLastDeployment) {
|
||||
environmentText = sprintf(
|
||||
__(
|
||||
'This job is creating a deployment to %{environmentLink} and will overwrite the %{deploymentLink}.',
|
||||
),
|
||||
{
|
||||
environmentLink: this.environmentLink,
|
||||
deploymentLink: this.deploymentLink(__('latest deployment')),
|
||||
},
|
||||
false,
|
||||
);
|
||||
} else {
|
||||
environmentText = sprintf(
|
||||
__('This job is creating a deployment to %{environmentLink}.'),
|
||||
{ environmentLink: this.environmentLink },
|
||||
false,
|
||||
);
|
||||
}
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
return environmentText;
|
||||
},
|
||||
environmentLink() {
|
||||
if (this.hasEnvironment) {
|
||||
return sprintf(
|
||||
'%{startLink}%{name}%{endLink}',
|
||||
{
|
||||
startLink: `<a href="${
|
||||
this.deploymentStatus.environment.environment_path
|
||||
}" class="js-environment-link">`,
|
||||
name: _.escape(this.deploymentStatus.environment.name),
|
||||
endLink: '</a>',
|
||||
},
|
||||
}
|
||||
|
||||
break;
|
||||
case 'failed':
|
||||
environmentText = sprintf(
|
||||
__('The deployment of this job to %{environmentLink} did not succeed.'),
|
||||
{ environmentLink: this.environmentLink },
|
||||
false,
|
||||
);
|
||||
}
|
||||
return '';
|
||||
},
|
||||
hasLastDeployment() {
|
||||
return this.hasEnvironment && this.deploymentStatus.environment.last_deployment;
|
||||
},
|
||||
lastDeployment() {
|
||||
return this.hasLastDeployment ? this.deploymentStatus.environment.last_deployment : {};
|
||||
},
|
||||
hasEnvironment() {
|
||||
return !_.isEmpty(this.deploymentStatus.environment);
|
||||
},
|
||||
lastDeploymentPath() {
|
||||
return !_.isEmpty(this.lastDeployment.deployable) ? this.lastDeployment.deployable.build_path : '';
|
||||
},
|
||||
break;
|
||||
case 'creating':
|
||||
if (this.hasLastDeployment) {
|
||||
environmentText = sprintf(
|
||||
__(
|
||||
'This job is creating a deployment to %{environmentLink} and will overwrite the %{deploymentLink}.',
|
||||
),
|
||||
{
|
||||
environmentLink: this.environmentLink,
|
||||
deploymentLink: this.deploymentLink(__('latest deployment')),
|
||||
},
|
||||
false,
|
||||
);
|
||||
} else {
|
||||
environmentText = sprintf(
|
||||
__('This job is creating a deployment to %{environmentLink}.'),
|
||||
{ environmentLink: this.environmentLink },
|
||||
false,
|
||||
);
|
||||
}
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
return environmentText;
|
||||
},
|
||||
methods: {
|
||||
deploymentLink(name) {
|
||||
environmentLink() {
|
||||
if (this.hasEnvironment) {
|
||||
return sprintf(
|
||||
'%{startLink}%{name}%{endLink}',
|
||||
{
|
||||
startLink: `<a href="${this.lastDeploymentPath}" class="js-job-deployment-link">`,
|
||||
name,
|
||||
startLink: `<a href="${
|
||||
this.deploymentStatus.environment.environment_path
|
||||
}" class="js-environment-link">`,
|
||||
name: _.escape(this.deploymentStatus.environment.name),
|
||||
endLink: '</a>',
|
||||
},
|
||||
false,
|
||||
);
|
||||
},
|
||||
}
|
||||
return '';
|
||||
},
|
||||
};
|
||||
hasLastDeployment() {
|
||||
return this.hasEnvironment && this.deploymentStatus.environment.last_deployment;
|
||||
},
|
||||
lastDeployment() {
|
||||
return this.hasLastDeployment ? this.deploymentStatus.environment.last_deployment : {};
|
||||
},
|
||||
hasEnvironment() {
|
||||
return !_.isEmpty(this.deploymentStatus.environment);
|
||||
},
|
||||
lastDeploymentPath() {
|
||||
return !_.isEmpty(this.lastDeployment.deployable)
|
||||
? this.lastDeployment.deployable.build_path
|
||||
: '';
|
||||
},
|
||||
},
|
||||
methods: {
|
||||
deploymentLink(name) {
|
||||
return sprintf(
|
||||
'%{startLink}%{name}%{endLink}',
|
||||
{
|
||||
startLink: `<a href="${this.lastDeploymentPath}" class="js-job-deployment-link">`,
|
||||
name,
|
||||
endLink: '</a>',
|
||||
},
|
||||
false,
|
||||
);
|
||||
},
|
||||
},
|
||||
};
|
||||
</script>
|
||||
<template>
|
||||
<div class="prepend-top-default js-environment-container">
|
||||
|
|
|
@ -1,28 +1,28 @@
|
|||
<script>
|
||||
import _ from 'underscore';
|
||||
import TimeagoTooltip from '~/vue_shared/components/time_ago_tooltip.vue';
|
||||
import _ from 'underscore';
|
||||
import TimeagoTooltip from '~/vue_shared/components/time_ago_tooltip.vue';
|
||||
|
||||
export default {
|
||||
components: {
|
||||
TimeagoTooltip,
|
||||
export default {
|
||||
components: {
|
||||
TimeagoTooltip,
|
||||
},
|
||||
props: {
|
||||
user: {
|
||||
type: Object,
|
||||
required: false,
|
||||
default: () => ({}),
|
||||
},
|
||||
props: {
|
||||
user: {
|
||||
type: Object,
|
||||
required: false,
|
||||
default: () => ({}),
|
||||
},
|
||||
erasedAt: {
|
||||
type: String,
|
||||
required: true,
|
||||
},
|
||||
erasedAt: {
|
||||
type: String,
|
||||
required: true,
|
||||
},
|
||||
computed: {
|
||||
isErasedByUser() {
|
||||
return !_.isEmpty(this.user);
|
||||
},
|
||||
},
|
||||
computed: {
|
||||
isErasedByUser() {
|
||||
return !_.isEmpty(this.user);
|
||||
},
|
||||
};
|
||||
},
|
||||
};
|
||||
</script>
|
||||
<template>
|
||||
<div class="prepend-top-default js-build-erased">
|
||||
|
|
|
@ -1,17 +1,17 @@
|
|||
<script>
|
||||
export default {
|
||||
name: 'JobLog',
|
||||
props: {
|
||||
trace: {
|
||||
type: String,
|
||||
required: true,
|
||||
},
|
||||
isComplete: {
|
||||
type: Boolean,
|
||||
required: true,
|
||||
},
|
||||
export default {
|
||||
name: 'JobLog',
|
||||
props: {
|
||||
trace: {
|
||||
type: String,
|
||||
required: true,
|
||||
},
|
||||
};
|
||||
isComplete: {
|
||||
type: Boolean,
|
||||
required: true,
|
||||
},
|
||||
},
|
||||
};
|
||||
</script>
|
||||
<template>
|
||||
<pre class="build-trace">
|
||||
|
|
|
@ -1,69 +1,68 @@
|
|||
<script>
|
||||
import { polyfillSticky } from '~/lib/utils/sticky';
|
||||
import Icon from '~/vue_shared/components/icon.vue';
|
||||
import tooltip from '~/vue_shared/directives/tooltip';
|
||||
import { numberToHumanSize } from '~/lib/utils/number_utils';
|
||||
import { sprintf } from '~/locale';
|
||||
import { polyfillSticky } from '~/lib/utils/sticky';
|
||||
import Icon from '~/vue_shared/components/icon.vue';
|
||||
import tooltip from '~/vue_shared/directives/tooltip';
|
||||
import { numberToHumanSize } from '~/lib/utils/number_utils';
|
||||
import { sprintf } from '~/locale';
|
||||
|
||||
export default {
|
||||
components: {
|
||||
Icon,
|
||||
export default {
|
||||
components: {
|
||||
Icon,
|
||||
},
|
||||
directives: {
|
||||
tooltip,
|
||||
},
|
||||
props: {
|
||||
erasePath: {
|
||||
type: String,
|
||||
required: false,
|
||||
default: null,
|
||||
},
|
||||
directives: {
|
||||
tooltip,
|
||||
size: {
|
||||
type: Number,
|
||||
required: true,
|
||||
},
|
||||
props: {
|
||||
erasePath: {
|
||||
type: String,
|
||||
required: false,
|
||||
default: null,
|
||||
},
|
||||
size: {
|
||||
type: Number,
|
||||
required: true,
|
||||
},
|
||||
rawPath: {
|
||||
type: String,
|
||||
required: false,
|
||||
default: null,
|
||||
},
|
||||
isScrollTopDisabled: {
|
||||
type: Boolean,
|
||||
required: true,
|
||||
},
|
||||
isScrollBottomDisabled: {
|
||||
type: Boolean,
|
||||
required: true,
|
||||
},
|
||||
isScrollingDown: {
|
||||
type: Boolean,
|
||||
required: true,
|
||||
},
|
||||
isTraceSizeVisible: {
|
||||
type: Boolean,
|
||||
required: true,
|
||||
},
|
||||
rawPath: {
|
||||
type: String,
|
||||
required: false,
|
||||
default: null,
|
||||
},
|
||||
computed: {
|
||||
jobLogSize() {
|
||||
return sprintf('Showing last %{size} of log -', {
|
||||
size: numberToHumanSize(this.size),
|
||||
});
|
||||
},
|
||||
isScrollTopDisabled: {
|
||||
type: Boolean,
|
||||
required: true,
|
||||
},
|
||||
mounted() {
|
||||
polyfillSticky(this.$el);
|
||||
isScrollBottomDisabled: {
|
||||
type: Boolean,
|
||||
required: true,
|
||||
},
|
||||
methods: {
|
||||
handleScrollToTop() {
|
||||
this.$emit('scrollJobLogTop');
|
||||
},
|
||||
handleScrollToBottom() {
|
||||
this.$emit('scrollJobLogBottom');
|
||||
},
|
||||
isScrollingDown: {
|
||||
type: Boolean,
|
||||
required: true,
|
||||
},
|
||||
|
||||
};
|
||||
isTraceSizeVisible: {
|
||||
type: Boolean,
|
||||
required: true,
|
||||
},
|
||||
},
|
||||
computed: {
|
||||
jobLogSize() {
|
||||
return sprintf('Showing last %{size} of log -', {
|
||||
size: numberToHumanSize(this.size),
|
||||
});
|
||||
},
|
||||
},
|
||||
mounted() {
|
||||
polyfillSticky(this.$el);
|
||||
},
|
||||
methods: {
|
||||
handleScrollToTop() {
|
||||
this.$emit('scrollJobLogTop');
|
||||
},
|
||||
handleScrollToBottom() {
|
||||
this.$emit('scrollJobLogBottom');
|
||||
},
|
||||
},
|
||||
};
|
||||
</script>
|
||||
<template>
|
||||
<div class="top-bar">
|
||||
|
|
|
@ -1,36 +1,36 @@
|
|||
<script>
|
||||
import _ from 'underscore';
|
||||
import CiIcon from '~/vue_shared/components/ci_icon.vue';
|
||||
import Icon from '~/vue_shared/components/icon.vue';
|
||||
import tooltip from '~/vue_shared/directives/tooltip';
|
||||
import _ from 'underscore';
|
||||
import CiIcon from '~/vue_shared/components/ci_icon.vue';
|
||||
import Icon from '~/vue_shared/components/icon.vue';
|
||||
import tooltip from '~/vue_shared/directives/tooltip';
|
||||
|
||||
export default {
|
||||
components: {
|
||||
CiIcon,
|
||||
Icon,
|
||||
export default {
|
||||
components: {
|
||||
CiIcon,
|
||||
Icon,
|
||||
},
|
||||
directives: {
|
||||
tooltip,
|
||||
},
|
||||
props: {
|
||||
jobs: {
|
||||
type: Array,
|
||||
required: true,
|
||||
},
|
||||
directives: {
|
||||
tooltip,
|
||||
jobId: {
|
||||
type: Number,
|
||||
required: true,
|
||||
},
|
||||
props: {
|
||||
jobs: {
|
||||
type: Array,
|
||||
required: true,
|
||||
},
|
||||
jobId: {
|
||||
type: Number,
|
||||
required: true,
|
||||
},
|
||||
},
|
||||
methods: {
|
||||
isJobActive(currentJobId) {
|
||||
return this.jobId === currentJobId;
|
||||
},
|
||||
methods: {
|
||||
isJobActive(currentJobId) {
|
||||
return this.jobId === currentJobId;
|
||||
},
|
||||
tooltipText(job) {
|
||||
return `${_.escape(job.name)} - ${job.status.tooltip}`;
|
||||
},
|
||||
tooltipText(job) {
|
||||
return `${_.escape(job.name)} - ${job.status.tooltip}`;
|
||||
},
|
||||
};
|
||||
},
|
||||
};
|
||||
</script>
|
||||
<template>
|
||||
<div class="js-jobs-container builds-container">
|
||||
|
|
|
@ -1,112 +1,112 @@
|
|||
<script>
|
||||
import _ from 'underscore';
|
||||
import { mapActions, mapState } from 'vuex';
|
||||
import timeagoMixin from '~/vue_shared/mixins/timeago';
|
||||
import { timeIntervalInWords } from '~/lib/utils/datetime_utility';
|
||||
import Icon from '~/vue_shared/components/icon.vue';
|
||||
import DetailRow from './sidebar_detail_row.vue';
|
||||
import ArtifactsBlock from './artifacts_block.vue';
|
||||
import TriggerBlock from './trigger_block.vue';
|
||||
import CommitBlock from './commit_block.vue';
|
||||
import StagesDropdown from './stages_dropdown.vue';
|
||||
import JobsContainer from './jobs_container.vue';
|
||||
import _ from 'underscore';
|
||||
import { mapActions, mapState } from 'vuex';
|
||||
import timeagoMixin from '~/vue_shared/mixins/timeago';
|
||||
import { timeIntervalInWords } from '~/lib/utils/datetime_utility';
|
||||
import Icon from '~/vue_shared/components/icon.vue';
|
||||
import DetailRow from './sidebar_detail_row.vue';
|
||||
import ArtifactsBlock from './artifacts_block.vue';
|
||||
import TriggerBlock from './trigger_block.vue';
|
||||
import CommitBlock from './commit_block.vue';
|
||||
import StagesDropdown from './stages_dropdown.vue';
|
||||
import JobsContainer from './jobs_container.vue';
|
||||
|
||||
export default {
|
||||
name: 'JobSidebar',
|
||||
components: {
|
||||
ArtifactsBlock,
|
||||
CommitBlock,
|
||||
DetailRow,
|
||||
Icon,
|
||||
TriggerBlock,
|
||||
StagesDropdown,
|
||||
JobsContainer,
|
||||
export default {
|
||||
name: 'JobSidebar',
|
||||
components: {
|
||||
ArtifactsBlock,
|
||||
CommitBlock,
|
||||
DetailRow,
|
||||
Icon,
|
||||
TriggerBlock,
|
||||
StagesDropdown,
|
||||
JobsContainer,
|
||||
},
|
||||
mixins: [timeagoMixin],
|
||||
props: {
|
||||
runnerHelpUrl: {
|
||||
type: String,
|
||||
required: false,
|
||||
default: '',
|
||||
},
|
||||
mixins: [timeagoMixin],
|
||||
props: {
|
||||
runnerHelpUrl: {
|
||||
type: String,
|
||||
required: false,
|
||||
default: '',
|
||||
},
|
||||
terminalPath: {
|
||||
type: String,
|
||||
required: false,
|
||||
default: null,
|
||||
},
|
||||
terminalPath: {
|
||||
type: String,
|
||||
required: false,
|
||||
default: null,
|
||||
},
|
||||
computed: {
|
||||
...mapState(['job', 'isLoading', 'stages', 'jobs']),
|
||||
coverage() {
|
||||
return `${this.job.coverage}%`;
|
||||
},
|
||||
duration() {
|
||||
return timeIntervalInWords(this.job.duration);
|
||||
},
|
||||
queued() {
|
||||
return timeIntervalInWords(this.job.queued);
|
||||
},
|
||||
runnerId() {
|
||||
return `${this.job.runner.description} (#${this.job.runner.id})`;
|
||||
},
|
||||
retryButtonClass() {
|
||||
let className =
|
||||
'js-retry-button float-right btn btn-retry d-none d-md-block d-lg-block d-xl-block';
|
||||
className +=
|
||||
this.job.status && this.job.recoverable ? ' btn-primary' : ' btn-inverted-secondary';
|
||||
return className;
|
||||
},
|
||||
hasTimeout() {
|
||||
return this.job.metadata != null && this.job.metadata.timeout_human_readable !== null;
|
||||
},
|
||||
timeout() {
|
||||
if (this.job.metadata == null) {
|
||||
return '';
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
...mapState(['job', 'isLoading', 'stages', 'jobs']),
|
||||
coverage() {
|
||||
return `${this.job.coverage}%`;
|
||||
},
|
||||
duration() {
|
||||
return timeIntervalInWords(this.job.duration);
|
||||
},
|
||||
queued() {
|
||||
return timeIntervalInWords(this.job.queued);
|
||||
},
|
||||
runnerId() {
|
||||
return `${this.job.runner.description} (#${this.job.runner.id})`;
|
||||
},
|
||||
retryButtonClass() {
|
||||
let className =
|
||||
'js-retry-button float-right btn btn-retry d-none d-md-block d-lg-block d-xl-block';
|
||||
className +=
|
||||
this.job.status && this.job.recoverable ? ' btn-primary' : ' btn-inverted-secondary';
|
||||
return className;
|
||||
},
|
||||
hasTimeout() {
|
||||
return this.job.metadata != null && this.job.metadata.timeout_human_readable !== null;
|
||||
},
|
||||
timeout() {
|
||||
if (this.job.metadata == null) {
|
||||
return '';
|
||||
}
|
||||
|
||||
let t = this.job.metadata.timeout_human_readable;
|
||||
if (this.job.metadata.timeout_source !== '') {
|
||||
t += ` (from ${this.job.metadata.timeout_source})`;
|
||||
}
|
||||
let t = this.job.metadata.timeout_human_readable;
|
||||
if (this.job.metadata.timeout_source !== '') {
|
||||
t += ` (from ${this.job.metadata.timeout_source})`;
|
||||
}
|
||||
|
||||
return t;
|
||||
},
|
||||
renderBlock() {
|
||||
return (
|
||||
this.job.merge_request ||
|
||||
this.job.duration ||
|
||||
this.job.finished_data ||
|
||||
this.job.erased_at ||
|
||||
this.job.queued ||
|
||||
this.job.runner ||
|
||||
this.job.coverage ||
|
||||
this.job.tags.length ||
|
||||
this.job.cancel_path
|
||||
);
|
||||
},
|
||||
hasArtifact() {
|
||||
return !_.isEmpty(this.job.artifact);
|
||||
},
|
||||
hasTriggers() {
|
||||
return !_.isEmpty(this.job.trigger);
|
||||
},
|
||||
hasStages() {
|
||||
return (
|
||||
(this.job &&
|
||||
this.job.pipeline &&
|
||||
this.job.pipeline.stages &&
|
||||
this.job.pipeline.stages.length > 0) ||
|
||||
false
|
||||
);
|
||||
},
|
||||
commit() {
|
||||
return this.job.pipeline.commit || {};
|
||||
},
|
||||
return t;
|
||||
},
|
||||
methods: {
|
||||
...mapActions(['fetchJobsForStage']),
|
||||
renderBlock() {
|
||||
return (
|
||||
this.job.merge_request ||
|
||||
this.job.duration ||
|
||||
this.job.finished_data ||
|
||||
this.job.erased_at ||
|
||||
this.job.queued ||
|
||||
this.job.runner ||
|
||||
this.job.coverage ||
|
||||
this.job.tags.length ||
|
||||
this.job.cancel_path
|
||||
);
|
||||
},
|
||||
};
|
||||
hasArtifact() {
|
||||
return !_.isEmpty(this.job.artifact);
|
||||
},
|
||||
hasTriggers() {
|
||||
return !_.isEmpty(this.job.trigger);
|
||||
},
|
||||
hasStages() {
|
||||
return (
|
||||
(this.job &&
|
||||
this.job.pipeline &&
|
||||
this.job.pipeline.stages &&
|
||||
this.job.pipeline.stages.length > 0) ||
|
||||
false
|
||||
);
|
||||
},
|
||||
commit() {
|
||||
return this.job.pipeline.commit || {};
|
||||
},
|
||||
},
|
||||
methods: {
|
||||
...mapActions(['fetchJobsForStage']),
|
||||
},
|
||||
};
|
||||
</script>
|
||||
<template>
|
||||
<aside
|
||||
|
|
|
@ -1,31 +1,31 @@
|
|||
<script>
|
||||
export default {
|
||||
name: 'SidebarDetailRow',
|
||||
props: {
|
||||
title: {
|
||||
type: String,
|
||||
required: false,
|
||||
default: '',
|
||||
},
|
||||
value: {
|
||||
type: String,
|
||||
required: true,
|
||||
},
|
||||
helpUrl: {
|
||||
type: String,
|
||||
required: false,
|
||||
default: '',
|
||||
},
|
||||
export default {
|
||||
name: 'SidebarDetailRow',
|
||||
props: {
|
||||
title: {
|
||||
type: String,
|
||||
required: false,
|
||||
default: '',
|
||||
},
|
||||
computed: {
|
||||
hasTitle() {
|
||||
return this.title.length > 0;
|
||||
},
|
||||
hasHelpURL() {
|
||||
return this.helpUrl.length > 0;
|
||||
},
|
||||
value: {
|
||||
type: String,
|
||||
required: true,
|
||||
},
|
||||
};
|
||||
helpUrl: {
|
||||
type: String,
|
||||
required: false,
|
||||
default: '',
|
||||
},
|
||||
},
|
||||
computed: {
|
||||
hasTitle() {
|
||||
return this.title.length > 0;
|
||||
},
|
||||
hasHelpURL() {
|
||||
return this.helpUrl.length > 0;
|
||||
},
|
||||
},
|
||||
};
|
||||
</script>
|
||||
<template>
|
||||
<p class="build-detail-row">
|
||||
|
|
|
@ -1,50 +1,50 @@
|
|||
<script>
|
||||
import _ from 'underscore';
|
||||
import CiIcon from '~/vue_shared/components/ci_icon.vue';
|
||||
import Icon from '~/vue_shared/components/icon.vue';
|
||||
import { __ } from '~/locale';
|
||||
import _ from 'underscore';
|
||||
import CiIcon from '~/vue_shared/components/ci_icon.vue';
|
||||
import Icon from '~/vue_shared/components/icon.vue';
|
||||
import { __ } from '~/locale';
|
||||
|
||||
export default {
|
||||
components: {
|
||||
CiIcon,
|
||||
Icon,
|
||||
export default {
|
||||
components: {
|
||||
CiIcon,
|
||||
Icon,
|
||||
},
|
||||
props: {
|
||||
pipeline: {
|
||||
type: Object,
|
||||
required: true,
|
||||
},
|
||||
props: {
|
||||
pipeline: {
|
||||
type: Object,
|
||||
required: true,
|
||||
},
|
||||
stages: {
|
||||
type: Array,
|
||||
required: true,
|
||||
},
|
||||
stages: {
|
||||
type: Array,
|
||||
required: true,
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
selectedStage: this.stages.length > 0 ? this.stages[0].name : __('More'),
|
||||
};
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
selectedStage: this.stages.length > 0 ? this.stages[0].name : __('More'),
|
||||
};
|
||||
},
|
||||
computed: {
|
||||
hasRef() {
|
||||
return !_.isEmpty(this.pipeline.ref);
|
||||
},
|
||||
computed: {
|
||||
hasRef() {
|
||||
return !_.isEmpty(this.pipeline.ref);
|
||||
},
|
||||
},
|
||||
watch: {
|
||||
// When the component is initially mounted it may start with an empty stages array.
|
||||
// Once the prop is updated, we set the first stage as the selected one
|
||||
stages(newVal) {
|
||||
if (newVal.length) {
|
||||
this.selectedStage = newVal[0].name;
|
||||
}
|
||||
},
|
||||
watch: {
|
||||
// When the component is initially mounted it may start with an empty stages array.
|
||||
// Once the prop is updated, we set the first stage as the selected one
|
||||
stages(newVal) {
|
||||
if (newVal.length) {
|
||||
this.selectedStage = newVal[0].name;
|
||||
}
|
||||
},
|
||||
},
|
||||
methods: {
|
||||
onStageClick(stage) {
|
||||
this.$emit('requestSidebarStageDropdown', stage);
|
||||
this.selectedStage = stage.name;
|
||||
},
|
||||
methods: {
|
||||
onStageClick(stage) {
|
||||
this.$emit('requestSidebarStageDropdown', stage);
|
||||
this.selectedStage = stage.name;
|
||||
},
|
||||
},
|
||||
};
|
||||
},
|
||||
};
|
||||
</script>
|
||||
<template>
|
||||
<div class="block-last dropdown">
|
||||
|
|
|
@ -1,27 +1,27 @@
|
|||
<script>
|
||||
export default {
|
||||
props: {
|
||||
trigger: {
|
||||
type: Object,
|
||||
required: true,
|
||||
},
|
||||
export default {
|
||||
props: {
|
||||
trigger: {
|
||||
type: Object,
|
||||
required: true,
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
areVariablesVisible: false,
|
||||
};
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
areVariablesVisible: false,
|
||||
};
|
||||
},
|
||||
computed: {
|
||||
hasVariables() {
|
||||
return this.trigger.variables && this.trigger.variables.length > 0;
|
||||
},
|
||||
computed: {
|
||||
hasVariables() {
|
||||
return this.trigger.variables && this.trigger.variables.length > 0;
|
||||
},
|
||||
},
|
||||
methods: {
|
||||
revealVariables() {
|
||||
this.areVariablesVisible = true;
|
||||
},
|
||||
methods: {
|
||||
revealVariables() {
|
||||
this.areVariablesVisible = true;
|
||||
},
|
||||
},
|
||||
};
|
||||
},
|
||||
};
|
||||
</script>
|
||||
|
||||
<template>
|
||||
|
|
|
@ -7,9 +7,10 @@ import mutations from './mutations';
|
|||
|
||||
Vue.use(Vuex);
|
||||
|
||||
export default () => new Vuex.Store({
|
||||
actions,
|
||||
mutations,
|
||||
getters,
|
||||
state: state(),
|
||||
});
|
||||
export default () =>
|
||||
new Vuex.Store({
|
||||
actions,
|
||||
mutations,
|
||||
getters,
|
||||
state: state(),
|
||||
});
|
||||
|
|
Loading…
Reference in a new issue