diff options
author | GitLab Bot <gitlab-bot@gitlab.com> | 2021-04-19 15:09:04 +0300 |
---|---|---|
committer | GitLab Bot <gitlab-bot@gitlab.com> | 2021-04-19 15:09:04 +0300 |
commit | c6af94ea4ea649171ff930b6bf94c73a5d03edb9 (patch) | |
tree | ceef77238b3a275a3a32b4e9f982b6d2f27e0c6b /app/assets/javascripts/pipeline_editor | |
parent | 3257ae3af07a4ad026be3c868e74ff82866fc400 (diff) |
Add latest changes from gitlab-org/gitlab@master
Diffstat (limited to 'app/assets/javascripts/pipeline_editor')
3 files changed, 107 insertions, 81 deletions
diff --git a/app/assets/javascripts/pipeline_editor/components/editor/ci_config_merged_preview.vue b/app/assets/javascripts/pipeline_editor/components/editor/ci_config_merged_preview.vue index d61136cda8d..455990f2791 100644 --- a/app/assets/javascripts/pipeline_editor/components/editor/ci_config_merged_preview.vue +++ b/app/assets/javascripts/pipeline_editor/components/editor/ci_config_merged_preview.vue @@ -1,29 +1,19 @@ <script> -import { GlAlert, GlIcon } from '@gitlab/ui'; +import { GlIcon } from '@gitlab/ui'; import { uniqueId } from 'lodash'; -import { __, s__ } from '~/locale'; -import { DEFAULT, INVALID_CI_CONFIG } from '~/pipelines/constants'; +import { s__ } from '~/locale'; import EditorLite from '~/vue_shared/components/editor_lite.vue'; export default { i18n: { viewOnlyMessage: s__('Pipelines|Merged YAML is view only'), }, - errorTexts: { - [INVALID_CI_CONFIG]: __('Your CI configuration file is invalid.'), - [DEFAULT]: __('An unknown error occurred.'), - }, components: { EditorLite, - GlAlert, GlIcon, }, inject: ['ciConfigPath'], props: { - isValid: { - type: Boolean, - required: true, - }, ciConfigData: { type: Object, required: true, @@ -35,66 +25,30 @@ export default { }; }, computed: { - failure() { - switch (this.failureType) { - case INVALID_CI_CONFIG: - return this.$options.errorTexts[INVALID_CI_CONFIG]; - default: - return this.$options.errorTexts[DEFAULT]; - } - }, fileGlobalId() { return `${this.ciConfigPath}-${uniqueId()}`; }, - hasError() { - return this.failureType; - }, mergedYaml() { return this.ciConfigData.mergedYaml; }, }, - watch: { - ciConfigData: { - immediate: true, - handler() { - if (!this.isValid) { - this.reportFailure(INVALID_CI_CONFIG); - } else if (this.hasError) { - this.resetFailure(); - } - }, - }, - }, - methods: { - reportFailure(errorType) { - this.failureType = errorType; - }, - resetFailure() { - this.failureType = null; - }, - }, }; </script> <template> <div> - <gl-alert v-if="hasError" variant="danger" :dismissible="false"> - {{ failure }} - </gl-alert> - <div v-else> - <div class="gl-display-flex gl-align-items-center"> - <gl-icon :size="16" name="lock" class="gl-text-gray-500 gl-mr-3" /> - {{ $options.i18n.viewOnlyMessage }} - </div> - <div class="gl-mt-3 gl-border-solid gl-border-gray-100 gl-border-1"> - <editor-lite - ref="editor" - :value="mergedYaml" - :file-name="ciConfigPath" - :file-global-id="fileGlobalId" - :editor-options="{ readOnly: true }" - v-on="$listeners" - /> - </div> + <div class="gl-display-flex gl-align-items-center"> + <gl-icon :size="16" name="lock" class="gl-text-gray-500 gl-mr-3" /> + {{ $options.i18n.viewOnlyMessage }} + </div> + <div class="gl-mt-3 gl-border-solid gl-border-gray-100 gl-border-1"> + <editor-lite + ref="editor" + :value="mergedYaml" + :file-name="ciConfigPath" + :file-global-id="fileGlobalId" + :editor-options="{ readOnly: true }" + v-on="$listeners" + /> </div> </div> </template> diff --git a/app/assets/javascripts/pipeline_editor/components/pipeline_editor_tabs.vue b/app/assets/javascripts/pipeline_editor/components/pipeline_editor_tabs.vue index 760d395ff2c..5acb3355b23 100644 --- a/app/assets/javascripts/pipeline_editor/components/pipeline_editor_tabs.vue +++ b/app/assets/javascripts/pipeline_editor/components/pipeline_editor_tabs.vue @@ -1,11 +1,13 @@ <script> -import { GlAlert, GlLoadingIcon, GlTabs, GlTab } from '@gitlab/ui'; +import { GlAlert, GlLoadingIcon, GlTabs } from '@gitlab/ui'; import { s__ } from '~/locale'; import PipelineGraph from '~/pipelines/components/pipeline_graph/pipeline_graph.vue'; import glFeatureFlagsMixin from '~/vue_shared/mixins/gl_feature_flags_mixin'; import { CREATE_TAB, + EDITOR_APP_STATUS_EMPTY, EDITOR_APP_STATUS_ERROR, + EDITOR_APP_STATUS_INVALID, EDITOR_APP_STATUS_LOADING, EDITOR_APP_STATUS_VALID, LINT_TAB, @@ -24,6 +26,17 @@ export default { tabGraph: s__('Pipelines|Visualize'), tabLint: s__('Pipelines|Lint'), tabMergedYaml: s__('Pipelines|View merged YAML'), + empty: { + visualization: s__( + 'PipelineEditor|The pipeline visualization is displayed when the CI/CD configuration file has valid syntax.', + ), + lint: s__( + 'PipelineEditor|The CI/CD configuration is continuously validated. Errors and warnings are displayed when the CI/CD configuration file is not empty.', + ), + merge: s__( + 'PipelineEditor|The merged YAML view is displayed when the CI/CD configuration file has valid syntax.', + ), + }, }, errorTexts: { loadMergedYaml: s__('Pipelines|Could not load merged YAML content'), @@ -40,7 +53,6 @@ export default { EditorTab, GlAlert, GlLoadingIcon, - GlTab, GlTabs, PipelineGraph, TextEditor, @@ -66,6 +78,12 @@ export default { // Not an invalid config and with `mergedYaml` data missing return this.appStatus === EDITOR_APP_STATUS_ERROR; }, + isEmpty() { + return this.appStatus === EDITOR_APP_STATUS_EMPTY; + }, + isInvalid() { + return this.appStatus === EDITOR_APP_STATUS_INVALID; + }, isValid() { return this.appStatus === EDITOR_APP_STATUS_VALID; }, @@ -91,9 +109,12 @@ export default { > <text-editor :value="ciFileContent" v-on="$listeners" /> </editor-tab> - <gl-tab + <editor-tab v-if="glFeatures.ciConfigVisualizationTab" class="gl-mb-3" + :empty-message="$options.i18n.empty.visualization" + :is-empty="isEmpty" + :is-invalid="isInvalid" :title="$options.i18n.tabGraph" lazy data-testid="visualization-tab" @@ -101,9 +122,11 @@ export default { > <gl-loading-icon v-if="isLoading" size="lg" class="gl-m-3" /> <pipeline-graph v-else :pipeline-data="ciConfigData" /> - </gl-tab> + </editor-tab> <editor-tab class="gl-mb-3" + :empty-message="$options.i18n.empty.lint" + :is-empty="isEmpty" :title="$options.i18n.tabLint" data-testid="lint-tab" @click="setCurrentTab($options.tabConstants.LINT_TAB)" @@ -111,9 +134,13 @@ export default { <gl-loading-icon v-if="isLoading" size="lg" class="gl-m-3" /> <ci-lint v-else :is-valid="isValid" :ci-config="ciConfigData" /> </editor-tab> - <gl-tab + <editor-tab v-if="glFeatures.ciConfigMergedTab" class="gl-mb-3" + :empty-message="$options.i18n.empty.merge" + :keep-component-mounted="false" + :is-empty="isEmpty" + :is-invalid="isInvalid" :title="$options.i18n.tabMergedYaml" lazy data-testid="merged-tab" @@ -123,12 +150,7 @@ export default { <gl-alert v-else-if="hasAppError" variant="danger" :dismissible="false"> {{ $options.errorTexts.loadMergedYaml }} </gl-alert> - <ci-config-merged-preview - v-else - :is-valid="isValid" - :ci-config-data="ciConfigData" - v-on="$listeners" - /> - </gl-tab> + <ci-config-merged-preview v-else :ci-config-data="ciConfigData" v-on="$listeners" /> + </editor-tab> </gl-tabs> </template> diff --git a/app/assets/javascripts/pipeline_editor/components/ui/editor_tab.vue b/app/assets/javascripts/pipeline_editor/components/ui/editor_tab.vue index ce8ee7493fe..7c032441a04 100644 --- a/app/assets/javascripts/pipeline_editor/components/ui/editor_tab.vue +++ b/app/assets/javascripts/pipeline_editor/components/ui/editor_tab.vue @@ -1,6 +1,6 @@ <script> -import { GlTab } from '@gitlab/ui'; - +import { GlAlert, GlTab } from '@gitlab/ui'; +import { __, s__ } from '~/locale'; /** * Wrapper of <gl-tab> to optionally lazily render this tab's content * when its shown **without dismounting after its hidden**. @@ -10,10 +10,10 @@ import { GlTab } from '@gitlab/ui'; * API is the same as <gl-tab>, for example: * * <gl-tabs> - * <editor-tab title="Tab 1" :lazy="true"> + * <editor-tab title="Tab 1" lazy> * lazily mounted content (gets mounted if this is first tab) * </editor-tab> - * <editor-tab title="Tab 2" :lazy="true"> + * <editor-tab title="Tab 2" lazy> * lazily mounted content * </editor-tab> * <editor-tab title="Tab 3"> @@ -25,10 +25,26 @@ import { GlTab } from '@gitlab/ui'; * so it's contents are not dismounted. * * lazy is "false" by default, as in <gl-tab>. + * + * It is also possible to pass the `isEmpty` and or `isInvalid` to let + * the tab component handle that state on its own. For example: + * + * * <gl-tabs> + * <editor-tab-with-status title="Tab 1" :is-empty="isEmpty" :is-invalid="isInvalid"> + * ... + * </editor-tab-with-status> + * Will be the same as normal, except it will only render the slot component + * if the status is not empty and not invalid. In any of these 2 cases, it will render + * a generic component and avoid mounting whatever it received in the slot. + * </gl-tabs> */ export default { + i18n: { + invalid: __('Your CI/CD configuration syntax is invalid. View Lint tab for more details.'), + }, components: { + GlAlert, GlTab, // Use a small renderless component to know when the tab content mounts because: // - gl-tab always gets mounted, even if lazy is `true`. See: @@ -40,29 +56,63 @@ export default { }, inheritAttrs: false, props: { + emptyMessage: { + type: String, + required: false, + default: s__( + 'PipelineEditor|This tab will be usable when the CI/CD configuration file is populated with valid syntax.', + ), + }, + isEmpty: { + type: Boolean, + required: false, + default: null, + }, + isInvalid: { + type: Boolean, + required: false, + default: null, + }, lazy: { type: Boolean, required: false, default: false, }, + keepComponentMounted: { + type: Boolean, + required: false, + default: true, + }, }, data() { return { isLazy: this.lazy, }; }, + computed: { + slots() { + return Object.keys(this.$slots); + }, + }, methods: { onContentMounted() { // When a child is first mounted make the entire tab - // permanently mounted by setting 'lazy' to false. - this.isLazy = false; + // permanently mounted by setting 'lazy' to false unless + // explicitly opted out. + if (this.keepComponentMounted) { + this.isLazy = false; + } }, }, }; </script> <template> <gl-tab :lazy="isLazy" v-bind="$attrs" v-on="$listeners"> - <slot v-for="slot in Object.keys($slots)" :name="slot"></slot> - <mount-spy @hook:mounted="onContentMounted" /> + <gl-alert v-if="isEmpty" variant="tip">{{ emptyMessage }}</gl-alert> + <gl-alert v-else-if="isInvalid" variant="danger">{{ $options.i18n.invalid }}</gl-alert> + <template v-else> + <slot v-for="slot in slots" :name="slot"></slot> + <mount-spy @hook:mounted="onContentMounted" /> + </template> </gl-tab> </template> |