diff options
Diffstat (limited to 'app/assets/javascripts/pipeline_wizard/components/wrapper.vue')
-rw-r--r-- | app/assets/javascripts/pipeline_wizard/components/wrapper.vue | 185 |
1 files changed, 185 insertions, 0 deletions
diff --git a/app/assets/javascripts/pipeline_wizard/components/wrapper.vue b/app/assets/javascripts/pipeline_wizard/components/wrapper.vue new file mode 100644 index 00000000000..b7207576ddc --- /dev/null +++ b/app/assets/javascripts/pipeline_wizard/components/wrapper.vue @@ -0,0 +1,185 @@ +<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> |