186 lines
5.3 KiB
Vue
186 lines
5.3 KiB
Vue
|
<script>
|
||
|
import { GlProgressBar } from '@gitlab/ui';
|
||
|
import { Document } from 'yaml';
|
||
|
import { merge } from '~/lib/utils/yaml';
|
||
|
import { __ } from '~/locale';
|
||
|
import { isValidStepSeq } from '~/pipeline_wizard/validators';
|
||
|
import YamlEditor from './editor.vue';
|
||
|
import WizardStep from './step.vue';
|
||
|
import CommitStep from './commit.vue';
|
||
|
|
||
|
export const i18n = {
|
||
|
stepNofN: __('Step %{currentStep} of %{stepCount}'),
|
||
|
draft: __('Draft: %{filename}'),
|
||
|
overlayMessage: __(`Start inputting changes and we will generate a
|
||
|
YAML-file for you to add to your repository`),
|
||
|
};
|
||
|
|
||
|
export default {
|
||
|
name: 'PipelineWizardWrapper',
|
||
|
i18n,
|
||
|
components: {
|
||
|
GlProgressBar,
|
||
|
YamlEditor,
|
||
|
WizardStep,
|
||
|
CommitStep,
|
||
|
},
|
||
|
props: {
|
||
|
steps: {
|
||
|
type: Object,
|
||
|
required: true,
|
||
|
validator: isValidStepSeq,
|
||
|
},
|
||
|
projectPath: {
|
||
|
type: String,
|
||
|
required: true,
|
||
|
},
|
||
|
defaultBranch: {
|
||
|
type: String,
|
||
|
required: true,
|
||
|
},
|
||
|
filename: {
|
||
|
type: String,
|
||
|
required: true,
|
||
|
},
|
||
|
},
|
||
|
data() {
|
||
|
return {
|
||
|
highlightPath: null,
|
||
|
currentStepIndex: 0,
|
||
|
// TODO: In order to support updating existing pipelines, the below
|
||
|
// should contain a parsed version of an existing .gitlab-ci.yml.
|
||
|
// See https://gitlab.com/gitlab-org/gitlab/-/issues/355306
|
||
|
compiled: new Document({}),
|
||
|
showPlaceholder: true,
|
||
|
pipelineBlob: null,
|
||
|
placeholder: this.getPlaceholder(),
|
||
|
};
|
||
|
},
|
||
|
computed: {
|
||
|
currentStepConfig() {
|
||
|
return this.steps.get(this.currentStepIndex);
|
||
|
},
|
||
|
currentStepInputs() {
|
||
|
return this.currentStepConfig.get('inputs').toJSON();
|
||
|
},
|
||
|
currentStepTemplate() {
|
||
|
return this.currentStepConfig.get('template', true);
|
||
|
},
|
||
|
currentStep() {
|
||
|
return this.currentStepIndex + 1;
|
||
|
},
|
||
|
stepCount() {
|
||
|
return this.steps.items.length + 1;
|
||
|
},
|
||
|
progress() {
|
||
|
return Math.ceil((this.currentStep / (this.stepCount + 1)) * 100);
|
||
|
},
|
||
|
isLastStep() {
|
||
|
return this.currentStep === this.stepCount;
|
||
|
},
|
||
|
},
|
||
|
watch: {
|
||
|
isLastStep(value) {
|
||
|
if (value) this.resetHighlight();
|
||
|
},
|
||
|
},
|
||
|
methods: {
|
||
|
resetHighlight() {
|
||
|
this.highlightPath = null;
|
||
|
},
|
||
|
onUpdate() {
|
||
|
this.showPlaceholder = false;
|
||
|
},
|
||
|
onEditorUpdate(blob) {
|
||
|
// TODO: In a later iteration, we could add a loopback allowing for
|
||
|
// changes from the editor to flow back into the model
|
||
|
// see https://gitlab.com/gitlab-org/gitlab/-/issues/355312
|
||
|
this.pipelineBlob = blob;
|
||
|
},
|
||
|
getPlaceholder() {
|
||
|
const doc = new Document({});
|
||
|
this.steps.items.forEach((tpl) => {
|
||
|
merge(doc, tpl.get('template').clone());
|
||
|
});
|
||
|
return doc;
|
||
|
},
|
||
|
},
|
||
|
};
|
||
|
</script>
|
||
|
|
||
|
<template>
|
||
|
<div class="row gl-mt-8">
|
||
|
<main class="col-md-6 gl-pr-8">
|
||
|
<header class="gl-mb-5">
|
||
|
<h3 class="text-secondary gl-mt-0" data-testid="step-count">
|
||
|
{{ sprintf($options.i18n.stepNofN, { currentStep, stepCount }) }}
|
||
|
</h3>
|
||
|
<gl-progress-bar :value="progress" variant="success" />
|
||
|
</header>
|
||
|
<section class="gl-mb-4">
|
||
|
<commit-step
|
||
|
v-if="isLastStep"
|
||
|
ref="step"
|
||
|
:default-branch="defaultBranch"
|
||
|
:file-content="pipelineBlob"
|
||
|
:filename="filename"
|
||
|
:project-path="projectPath"
|
||
|
@back="currentStepIndex--"
|
||
|
/>
|
||
|
<wizard-step
|
||
|
v-else
|
||
|
:key="currentStepIndex"
|
||
|
ref="step"
|
||
|
:compiled.sync="compiled"
|
||
|
:has-next-step="currentStepIndex < steps.items.length"
|
||
|
:has-previous-step="currentStepIndex > 0"
|
||
|
:highlight.sync="highlightPath"
|
||
|
:inputs="currentStepInputs"
|
||
|
:template="currentStepTemplate"
|
||
|
@back="currentStepIndex--"
|
||
|
@next="currentStepIndex++"
|
||
|
@update:compiled="onUpdate"
|
||
|
/>
|
||
|
</section>
|
||
|
</main>
|
||
|
<aside class="col-md-6 gl-pt-3">
|
||
|
<div
|
||
|
class="gl-border-1 gl-border-gray-100 gl-border-solid border-radius-default gl-bg-gray-10"
|
||
|
>
|
||
|
<h6 class="gl-p-2 gl-px-4 text-secondary" data-testid="editor-header">
|
||
|
{{ sprintf($options.i18n.draft, { filename }) }}
|
||
|
</h6>
|
||
|
<div class="gl-relative gl-overflow-hidden">
|
||
|
<yaml-editor
|
||
|
:aria-hidden="showPlaceholder"
|
||
|
:doc="showPlaceholder ? placeholder : compiled"
|
||
|
:filename="filename"
|
||
|
:highlight="highlightPath"
|
||
|
class="gl-w-full"
|
||
|
@update:yaml="onEditorUpdate"
|
||
|
/>
|
||
|
<div
|
||
|
v-if="showPlaceholder"
|
||
|
class="gl-absolute gl-top-0 gl-right-0 gl-bottom-0 gl-left-0 gl-filter-blur-1"
|
||
|
data-testid="placeholder-overlay"
|
||
|
>
|
||
|
<div
|
||
|
class="gl-absolute gl-top-0 gl-right-0 gl-bottom-0 gl-left-0 bg-white gl-opacity-5 gl-z-index-2"
|
||
|
></div>
|
||
|
<div
|
||
|
class="gl-relative gl-h-full gl-display-flex gl-align-items-center gl-justify-content-center gl-z-index-3"
|
||
|
>
|
||
|
<div class="gl-max-w-34">
|
||
|
<h4 data-testid="filename">{{ filename }}</h4>
|
||
|
<p data-testid="description">
|
||
|
{{ $options.i18n.overlayMessage }}
|
||
|
</p>
|
||
|
</div>
|
||
|
</div>
|
||
|
</div>
|
||
|
</div>
|
||
|
</div>
|
||
|
</aside>
|
||
|
</div>
|
||
|
</template>
|