1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
|
<script>
import { GlLoadingIcon, GlAlert, GlTabs, GlTab } from '@gitlab/ui';
import { __, s__, sprintf } from '~/locale';
import TextEditor from './components/text_editor.vue';
import PipelineGraph from '~/pipelines/components/pipeline_graph/pipeline_graph.vue';
import getBlobContent from './graphql/queries/blob_content.graphql';
export default {
components: {
GlLoadingIcon,
GlAlert,
GlTabs,
GlTab,
TextEditor,
PipelineGraph,
},
props: {
projectPath: {
type: String,
required: true,
},
defaultBranch: {
type: String,
required: false,
default: null,
},
ciConfigPath: {
type: String,
required: true,
},
},
data() {
return {
error: null,
content: '',
editorIsReady: false,
};
},
apollo: {
content: {
query: getBlobContent,
variables() {
return {
projectPath: this.projectPath,
path: this.ciConfigPath,
ref: this.defaultBranch,
};
},
update(data) {
return data?.blobContent?.rawData;
},
error(error) {
this.error = error;
},
},
},
computed: {
loading() {
return this.$apollo.queries.content.loading;
},
errorMessage() {
const { message: generalReason, networkError } = this.error ?? {};
const { data } = networkError?.response ?? {};
// 404 for missing file uses `message`
// 400 for a missing ref uses `error`
const networkReason = data?.message ?? data?.error;
const reason = networkReason ?? generalReason ?? this.$options.i18n.unknownError;
return sprintf(this.$options.i18n.errorMessageWithReason, { reason });
},
pipelineData() {
// Note data will loaded as part of https://gitlab.com/gitlab-org/gitlab/-/issues/263141
return {};
},
},
i18n: {
unknownError: __('Unknown Error'),
errorMessageWithReason: s__('Pipelines|CI file could not be loaded: %{reason}'),
tabEdit: s__('Pipelines|Write pipeline configuration'),
tabGraph: s__('Pipelines|Visualize'),
},
};
</script>
<template>
<div class="gl-mt-4">
<gl-alert v-if="error" :dismissible="false" variant="danger">{{ errorMessage }}</gl-alert>
<div class="gl-mt-4">
<gl-loading-icon v-if="loading" size="lg" />
<div v-else class="file-editor">
<gl-tabs>
<!-- editor should be mounted when its tab is visible, so the container has a size -->
<gl-tab :title="$options.i18n.tabEdit" :lazy="!editorIsReady">
<!-- editor should be mounted only once, when the tab is displayed -->
<text-editor v-model="content" @editor-ready="editorIsReady = true" />
</gl-tab>
<gl-tab :title="$options.i18n.tabGraph">
<pipeline-graph :pipeline-data="pipelineData" />
</gl-tab>
</gl-tabs>
</div>
</div>
</div>
</template>
|