summaryrefslogtreecommitdiff
path: root/app/assets/javascripts/repository
diff options
context:
space:
mode:
Diffstat (limited to 'app/assets/javascripts/repository')
-rw-r--r--app/assets/javascripts/repository/components/blob_button_group.vue14
-rw-r--r--app/assets/javascripts/repository/components/blob_content_viewer.vue77
-rw-r--r--app/assets/javascripts/repository/components/blob_edit.vue78
-rw-r--r--app/assets/javascripts/repository/components/blob_viewers/audio_viewer.vue20
-rw-r--r--app/assets/javascripts/repository/components/blob_viewers/csv_viewer.vue26
-rw-r--r--app/assets/javascripts/repository/components/blob_viewers/download_viewer.vue2
-rw-r--r--app/assets/javascripts/repository/components/blob_viewers/image_viewer.vue2
-rw-r--r--app/assets/javascripts/repository/components/blob_viewers/index.js2
-rw-r--r--app/assets/javascripts/repository/components/blob_viewers/lfs_viewer.vue2
-rw-r--r--app/assets/javascripts/repository/components/blob_viewers/pdf_viewer.vue2
-rw-r--r--app/assets/javascripts/repository/components/breadcrumbs.vue13
-rw-r--r--app/assets/javascripts/repository/components/delete_blob_modal.vue2
-rw-r--r--app/assets/javascripts/repository/constants.js10
-rw-r--r--app/assets/javascripts/repository/index.js4
-rw-r--r--app/assets/javascripts/repository/queries/application_info.query.graphql3
-rw-r--r--app/assets/javascripts/repository/queries/blob_info.query.graphql4
-rw-r--r--app/assets/javascripts/repository/queries/user_info.query.graphql8
17 files changed, 155 insertions, 114 deletions
diff --git a/app/assets/javascripts/repository/components/blob_button_group.vue b/app/assets/javascripts/repository/components/blob_button_group.vue
index 857795c71b0..d79ccde61a8 100644
--- a/app/assets/javascripts/repository/components/blob_button_group.vue
+++ b/app/assets/javascripts/repository/components/blob_button_group.vue
@@ -7,6 +7,8 @@ import getRefMixin from '../mixins/get_ref';
import DeleteBlobModal from './delete_blob_modal.vue';
import UploadBlobModal from './upload_blob_modal.vue';
+const REPLACE_BLOB_MODAL_ID = 'modal-replace-blob';
+
export default {
i18n: {
replace: __('Replace'),
@@ -76,9 +78,6 @@ export default {
},
},
computed: {
- replaceModalId() {
- return uniqueId('replace-modal');
- },
replaceModalTitle() {
return sprintf(__('Replace %{name}'), { name: this.name });
},
@@ -95,13 +94,14 @@ export default {
methods: {
showModal(modalId) {
if (this.showForkSuggestion) {
- this.$emit('fork');
+ this.$emit('fork', 'view');
return;
}
this.$refs[modalId].show();
},
},
+ replaceBlobModalId: REPLACE_BLOB_MODAL_ID,
};
</script>
@@ -118,7 +118,7 @@ export default {
data-testid="lock"
:data-qa-selector="lockBtnQASelector"
/>
- <gl-button data-testid="replace" @click="showModal(replaceModalId)">
+ <gl-button data-testid="replace" @click="showModal($options.replaceBlobModalId)">
{{ $options.i18n.replace }}
</gl-button>
<gl-button data-testid="delete" @click="showModal(deleteModalId)">
@@ -126,8 +126,8 @@ export default {
</gl-button>
</gl-button-group>
<upload-blob-modal
- :ref="replaceModalId"
- :modal-id="replaceModalId"
+ :ref="$options.replaceBlobModalId"
+ :modal-id="$options.replaceBlobModalId"
:modal-title="replaceModalTitle"
:commit-message="replaceModalTitle"
:target-branch="targetBranch || ref"
diff --git a/app/assets/javascripts/repository/components/blob_content_viewer.vue b/app/assets/javascripts/repository/components/blob_content_viewer.vue
index 52963b49f68..85652301f4d 100644
--- a/app/assets/javascripts/repository/components/blob_content_viewer.vue
+++ b/app/assets/javascripts/repository/components/blob_content_viewer.vue
@@ -10,11 +10,14 @@ import { isLoggedIn } from '~/lib/utils/common_utils';
import { __ } from '~/locale';
import { redirectTo } from '~/lib/utils/url_utility';
import glFeatureFlagMixin from '~/vue_shared/mixins/gl_feature_flags_mixin';
+import WebIdeLink from '~/vue_shared/components/web_ide_link.vue';
+import CodeIntelligence from '~/code_navigation/components/app.vue';
import getRefMixin from '../mixins/get_ref';
import blobInfoQuery from '../queries/blob_info.query.graphql';
+import userInfoQuery from '../queries/user_info.query.graphql';
+import applicationInfoQuery from '../queries/application_info.query.graphql';
import { DEFAULT_BLOB_INFO, TEXT_FILE_TYPE, LFS_STORAGE } from '../constants';
import BlobButtonGroup from './blob_button_group.vue';
-import BlobEdit from './blob_edit.vue';
import ForkSuggestion from './fork_suggestion.vue';
import { loadViewer } from './blob_viewers';
@@ -24,12 +27,13 @@ export default {
},
components: {
BlobHeader,
- BlobEdit,
BlobButtonGroup,
BlobContent,
GlLoadingIcon,
GlButton,
ForkSuggestion,
+ WebIdeLink,
+ CodeIntelligence,
},
mixins: [getRefMixin, glFeatureFlagMixin()],
inject: {
@@ -38,6 +42,18 @@ export default {
},
},
apollo: {
+ gitpodEnabled: {
+ query: applicationInfoQuery,
+ error() {
+ this.displayError();
+ },
+ },
+ currentUser: {
+ query: userInfoQuery,
+ error() {
+ this.displayError();
+ },
+ },
project: {
query: blobInfoQuery,
variables() {
@@ -78,8 +94,11 @@ export default {
legacySimpleViewer: null,
isBinary: false,
isLoadingLegacyViewer: false,
+ isRenderingLegacyTextViewer: false,
activeViewerType: SIMPLE_BLOB_VIEWER,
- project: DEFAULT_BLOB_INFO,
+ project: DEFAULT_BLOB_INFO.project,
+ gitpodEnabled: DEFAULT_BLOB_INFO.gitpodEnabled,
+ currentUser: DEFAULT_BLOB_INFO.currentUser,
};
},
computed: {
@@ -142,9 +161,13 @@ export default {
return this.isLoggedIn && !canModifyBlob && createMergeRequestIn && forkProject;
},
forkPath() {
- return this.forkTarget === 'ide'
- ? this.blobInfo.ideForkAndEditPath
- : this.blobInfo.forkAndEditPath;
+ const forkPaths = {
+ ide: this.blobInfo.ideForkAndEditPath,
+ simple: this.blobInfo.forkAndEditPath,
+ view: this.blobInfo.forkAndViewPath,
+ };
+
+ return forkPaths[this.forkTarget];
},
isUsingLfs() {
return this.blobInfo.storedExternally && this.blobInfo.externalStorage === LFS_STORAGE;
@@ -163,7 +186,13 @@ export default {
.get(`${this.blobInfo.webPath}?format=json&viewer=${type}`)
.then(({ data: { html, binary } }) => {
if (type === SIMPLE_BLOB_VIEWER) {
+ this.isRenderingLegacyTextViewer = true;
+
this.legacySimpleViewer = html;
+
+ window.requestIdleCallback(() => {
+ this.isRenderingLegacyTextViewer = false;
+ });
} else {
this.legacyRichViewer = html;
}
@@ -213,26 +242,25 @@ export default {
@viewer-changed="switchViewer"
>
<template #actions>
- <blob-edit
+ <web-ide-link
v-if="!blobInfo.archived"
:show-edit-button="!isBinaryFileType"
- :edit-path="blobInfo.editBlobPath"
- :web-ide-path="blobInfo.ideEditPath"
+ class="gl-mr-3"
+ :edit-url="blobInfo.editBlobPath"
+ :web-ide-url="blobInfo.ideEditPath"
:needs-to-fork="showForkSuggestion"
+ :show-pipeline-editor-button="Boolean(blobInfo.pipelineEditorPath)"
+ :pipeline-editor-url="blobInfo.pipelineEditorPath"
+ :gitpod-url="blobInfo.gitpodBlobUrl"
+ :show-gitpod-button="gitpodEnabled"
+ :gitpod-enabled="currentUser && currentUser.gitpodEnabled"
+ :user-preferences-gitpod-path="currentUser && currentUser.preferencesGitpodPath"
+ :user-profile-enable-gitpod-path="currentUser && currentUser.profileEnableGitpodPath"
+ is-blob
+ disable-fork-modal
@edit="editBlob"
/>
- <gl-button
- v-if="blobInfo.pipelineEditorPath"
- class="gl-mr-3"
- category="secondary"
- variant="confirm"
- data-testid="pipeline-editor"
- :href="blobInfo.pipelineEditorPath"
- >
- {{ $options.i18n.pipelineEditor }}
- </gl-button>
-
<blob-button-group
v-if="isLoggedIn && !blobInfo.archived"
:path="path"
@@ -246,7 +274,7 @@ export default {
:is-locked="Boolean(pathLockedByUser)"
:can-lock="canLock"
:show-fork-suggestion="showForkSuggestion"
- @fork="setForkTarget('ide')"
+ @fork="setForkTarget('view')"
/>
</template>
</blob-header>
@@ -265,8 +293,15 @@ export default {
:active-viewer="viewer"
:hide-line-numbers="true"
:loading="isLoadingLegacyViewer"
+ :data-loading="isRenderingLegacyTextViewer"
/>
<component :is="blobViewer" v-else :blob="blobInfo" class="blob-viewer" />
+ <code-intelligence
+ v-if="blobViewer || legacyViewerLoaded"
+ :code-navigation-path="blobInfo.codeNavigationPath"
+ :blob-path="blobInfo.path"
+ :path-prefix="blobInfo.projectBlobPathRoot"
+ />
</div>
</div>
</template>
diff --git a/app/assets/javascripts/repository/components/blob_edit.vue b/app/assets/javascripts/repository/components/blob_edit.vue
deleted file mode 100644
index 69e2bd563c9..00000000000
--- a/app/assets/javascripts/repository/components/blob_edit.vue
+++ /dev/null
@@ -1,78 +0,0 @@
-<script>
-import { GlButton } from '@gitlab/ui';
-import { __ } from '~/locale';
-import WebIdeLink from '~/vue_shared/components/web_ide_link.vue';
-import glFeatureFlagsMixin from '~/vue_shared/mixins/gl_feature_flags_mixin';
-
-export default {
- i18n: {
- edit: __('Edit'),
- webIde: __('Web IDE'),
- },
- components: {
- GlButton,
- WebIdeLink,
- },
- mixins: [glFeatureFlagsMixin()],
- props: {
- showEditButton: {
- type: Boolean,
- required: true,
- },
- editPath: {
- type: String,
- required: true,
- },
- webIdePath: {
- type: String,
- required: true,
- },
- needsToFork: {
- type: Boolean,
- required: false,
- default: false,
- },
- },
- methods: {
- onEdit(target) {
- this.$emit('edit', target);
- },
- },
-};
-</script>
-
-<template>
- <web-ide-link
- v-if="glFeatures.consolidatedEditButton"
- :show-edit-button="showEditButton"
- class="gl-mr-3"
- :edit-url="editPath"
- :web-ide-url="webIdePath"
- :needs-to-fork="needsToFork"
- :is-blob="true"
- disable-fork-modal
- @edit="onEdit"
- />
- <div v-else>
- <gl-button
- v-if="showEditButton"
- class="gl-mr-2"
- category="primary"
- variant="confirm"
- data-testid="edit"
- @click="onEdit('simple')"
- >
- {{ $options.i18n.edit }}
- </gl-button>
-
- <gl-button
- class="gl-mr-3"
- category="primary"
- variant="confirm"
- data-testid="web-ide"
- @click="onEdit('ide')"
- >
- {{ $options.i18n.webIde }}
- </gl-button>
- </div>
-</template>
diff --git a/app/assets/javascripts/repository/components/blob_viewers/audio_viewer.vue b/app/assets/javascripts/repository/components/blob_viewers/audio_viewer.vue
new file mode 100644
index 00000000000..048730c02c1
--- /dev/null
+++ b/app/assets/javascripts/repository/components/blob_viewers/audio_viewer.vue
@@ -0,0 +1,20 @@
+<script>
+export default {
+ props: {
+ blob: {
+ type: Object,
+ required: true,
+ },
+ },
+ data() {
+ return {
+ src: this.blob.rawPath,
+ };
+ },
+};
+</script>
+<template>
+ <div class="gl-text-center gl-p-7">
+ <audio :src="src" controls data-testid="audio"></audio>
+ </div>
+</template>
diff --git a/app/assets/javascripts/repository/components/blob_viewers/csv_viewer.vue b/app/assets/javascripts/repository/components/blob_viewers/csv_viewer.vue
new file mode 100644
index 00000000000..86a0bb9fad0
--- /dev/null
+++ b/app/assets/javascripts/repository/components/blob_viewers/csv_viewer.vue
@@ -0,0 +1,26 @@
+<script>
+import CsvViewer from '~/blob/csv/csv_viewer.vue';
+
+export default {
+ components: {
+ CsvViewer,
+ },
+ props: {
+ blob: {
+ type: Object,
+ required: true,
+ },
+ },
+ data() {
+ return {
+ url: this.blob.rawPath,
+ };
+ },
+};
+</script>
+
+<template>
+ <div>
+ <csv-viewer :csv="url" remote-file data-testid="csv" />
+ </div>
+</template>
diff --git a/app/assets/javascripts/repository/components/blob_viewers/download_viewer.vue b/app/assets/javascripts/repository/components/blob_viewers/download_viewer.vue
index f7b318c64d9..be5e9685ccd 100644
--- a/app/assets/javascripts/repository/components/blob_viewers/download_viewer.vue
+++ b/app/assets/javascripts/repository/components/blob_viewers/download_viewer.vue
@@ -17,7 +17,7 @@ export default {
data() {
return {
fileName: this.blob.name,
- filePath: this.blob.rawPath,
+ filePath: this.blob.externalStorageUrl || this.blob.rawPath,
fileSize: this.blob.rawSize || 0,
};
},
diff --git a/app/assets/javascripts/repository/components/blob_viewers/image_viewer.vue b/app/assets/javascripts/repository/components/blob_viewers/image_viewer.vue
index 5027f7877aa..014f1abc121 100644
--- a/app/assets/javascripts/repository/components/blob_viewers/image_viewer.vue
+++ b/app/assets/javascripts/repository/components/blob_viewers/image_viewer.vue
@@ -16,6 +16,6 @@ export default {
</script>
<template>
<div class="gl-text-center gl-p-7 gl-bg-gray-50">
- <img :src="url" :alt="alt" data-testid="image" />
+ <img :src="url" :alt="alt" data-testid="image" class="gl-max-w-full" />
</div>
</template>
diff --git a/app/assets/javascripts/repository/components/blob_viewers/index.js b/app/assets/javascripts/repository/components/blob_viewers/index.js
index e942f59e7d8..cbe18ea396e 100644
--- a/app/assets/javascripts/repository/components/blob_viewers/index.js
+++ b/app/assets/javascripts/repository/components/blob_viewers/index.js
@@ -1,4 +1,5 @@
const viewers = {
+ csv: () => import('./csv_viewer.vue'),
download: () => import('./download_viewer.vue'),
image: () => import('./image_viewer.vue'),
video: () => import('./video_viewer.vue'),
@@ -6,6 +7,7 @@ const viewers = {
text: () => import('~/vue_shared/components/source_viewer/source_viewer.vue'),
pdf: () => import('./pdf_viewer.vue'),
lfs: () => import('./lfs_viewer.vue'),
+ audio: () => import('./audio_viewer.vue'),
};
export const loadViewer = (type, isUsingLfs) => {
diff --git a/app/assets/javascripts/repository/components/blob_viewers/lfs_viewer.vue b/app/assets/javascripts/repository/components/blob_viewers/lfs_viewer.vue
index 6dc7e10662e..9d39764e9a4 100644
--- a/app/assets/javascripts/repository/components/blob_viewers/lfs_viewer.vue
+++ b/app/assets/javascripts/repository/components/blob_viewers/lfs_viewer.vue
@@ -21,7 +21,7 @@ export default {
data() {
return {
fileName: this.blob.name,
- filePath: this.blob.rawPath,
+ filePath: this.blob.externalStorageUrl || this.blob.rawPath,
};
},
};
diff --git a/app/assets/javascripts/repository/components/blob_viewers/pdf_viewer.vue b/app/assets/javascripts/repository/components/blob_viewers/pdf_viewer.vue
index c3df5984426..37c8f636757 100644
--- a/app/assets/javascripts/repository/components/blob_viewers/pdf_viewer.vue
+++ b/app/assets/javascripts/repository/components/blob_viewers/pdf_viewer.vue
@@ -18,7 +18,7 @@ export default {
},
data() {
return {
- url: this.blob.rawPath,
+ url: this.blob.externalStorageUrl || this.blob.rawPath,
fileSize: this.blob.rawSize,
totalPages: 0,
};
diff --git a/app/assets/javascripts/repository/components/breadcrumbs.vue b/app/assets/javascripts/repository/components/breadcrumbs.vue
index d3717f10ec7..08faf19d12a 100644
--- a/app/assets/javascripts/repository/components/breadcrumbs.vue
+++ b/app/assets/javascripts/repository/components/breadcrumbs.vue
@@ -148,11 +148,16 @@ export default {
.reduce(
(acc, name, i) => {
const path = joinPaths(i > 0 ? acc[i].path : '', escapeFileUrl(name));
+ const isLastPath = i === this.currentPath.split('/').length - 1;
+ const to =
+ this.isBlobPath && isLastPath
+ ? `/-/blob/${joinPaths(this.escapedRef, path)}`
+ : `/-/tree/${joinPaths(this.escapedRef, path)}`;
return acc.concat({
name,
path,
- to: `/-/tree/${joinPaths(this.escapedRef, path)}`,
+ to,
});
},
[
@@ -274,9 +279,11 @@ export default {
return items;
},
+ isBlobPath() {
+ return this.$route.name === 'blobPath' || this.$route.name === 'blobPathDecoded';
+ },
renderAddToTreeDropdown() {
- const isBlobPath = this.$route.name === 'blobPath' || this.$route.name === 'blobPathDecoded';
- return !isBlobPath && (this.canCollaborate || this.canCreateMrFromFork);
+ return !this.isBlobPath && (this.canCollaborate || this.canCreateMrFromFork);
},
},
methods: {
diff --git a/app/assets/javascripts/repository/components/delete_blob_modal.vue b/app/assets/javascripts/repository/components/delete_blob_modal.vue
index f3c9aea36f1..baf8449b188 100644
--- a/app/assets/javascripts/repository/components/delete_blob_modal.vue
+++ b/app/assets/javascripts/repository/components/delete_blob_modal.vue
@@ -87,7 +87,7 @@ export default {
fields: {
// fields key must match case of form name for validation directive to work
commit_message: initFormField({ value: this.commitMessage }),
- branch_name: initFormField({ value: this.targetBranch }),
+ branch_name: initFormField({ value: this.targetBranch, skipValidation: !this.canPushCode }),
},
};
return {
diff --git a/app/assets/javascripts/repository/constants.js b/app/assets/javascripts/repository/constants.js
index e206d9bfbd2..bb9d3180be8 100644
--- a/app/assets/javascripts/repository/constants.js
+++ b/app/assets/javascripts/repository/constants.js
@@ -27,6 +27,12 @@ export const PDF_MAX_PAGE_LIMIT = 50;
export const ROW_APPEAR_DELAY = 150;
export const DEFAULT_BLOB_INFO = {
+ gitpodEnabled: false,
+ currentUser: {
+ gitpodEnabled: false,
+ preferencesGitpodPath: null,
+ profileEnableGitpodPath: null,
+ },
userPermissions: {
pushCode: false,
downloadCode: false,
@@ -49,9 +55,13 @@ export const DEFAULT_BLOB_INFO = {
tooLarge: false,
path: '',
editBlobPath: '',
+ gitpodBlobUrl: '',
ideEditPath: '',
forkAndEditPath: '',
ideForkAndEditPath: '',
+ codeNavigationPath: '',
+ projectBlobPathRoot: '',
+ forkAndViewPath: '',
storedExternally: false,
externalStorage: '',
environmentFormattedExternalUrl: '',
diff --git a/app/assets/javascripts/repository/index.js b/app/assets/javascripts/repository/index.js
index 120c32caefd..b38a1cfdc7b 100644
--- a/app/assets/javascripts/repository/index.js
+++ b/app/assets/javascripts/repository/index.js
@@ -1,10 +1,12 @@
import { GlButton } from '@gitlab/ui';
import Vue from 'vue';
+import Vuex from 'vuex';
import { parseBoolean } from '~/lib/utils/common_utils';
import { escapeFileUrl } from '~/lib/utils/url_utility';
import { __ } from '~/locale';
import initWebIdeLink from '~/pages/projects/shared/web_ide_link';
import PerformancePlugin from '~/performance/vue_performance_plugin';
+import createStore from '~/code_navigation/store';
import App from './components/app.vue';
import Breadcrumbs from './components/breadcrumbs.vue';
import DirectoryDownloadLinks from './components/directory_download_links.vue';
@@ -19,6 +21,7 @@ import createRouter from './router';
import { updateFormAction } from './utils/dom';
import { setTitle } from './utils/title';
+Vue.use(Vuex);
Vue.use(PerformancePlugin, {
components: ['SimpleViewer', 'BlobContent'],
});
@@ -200,6 +203,7 @@ export default function setupVueRepositoryList() {
// eslint-disable-next-line no-new
new Vue({
el,
+ store: createStore(),
router,
apolloProvider,
render(h) {
diff --git a/app/assets/javascripts/repository/queries/application_info.query.graphql b/app/assets/javascripts/repository/queries/application_info.query.graphql
new file mode 100644
index 00000000000..fd69de39f75
--- /dev/null
+++ b/app/assets/javascripts/repository/queries/application_info.query.graphql
@@ -0,0 +1,3 @@
+query getApplicationInfo {
+ gitpodEnabled
+}
diff --git a/app/assets/javascripts/repository/queries/blob_info.query.graphql b/app/assets/javascripts/repository/queries/blob_info.query.graphql
index 78323fdc5f4..8baee80e5d6 100644
--- a/app/assets/javascripts/repository/queries/blob_info.query.graphql
+++ b/app/assets/javascripts/repository/queries/blob_info.query.graphql
@@ -28,9 +28,13 @@ query getBlobInfo(
language
path
editBlobPath
+ gitpodBlobUrl
ideEditPath
forkAndEditPath
ideForkAndEditPath
+ codeNavigationPath
+ projectBlobPathRoot
+ forkAndViewPath
environmentFormattedExternalUrl
environmentExternalUrlForRouteMap
canModifyBlob
diff --git a/app/assets/javascripts/repository/queries/user_info.query.graphql b/app/assets/javascripts/repository/queries/user_info.query.graphql
new file mode 100644
index 00000000000..114947a423d
--- /dev/null
+++ b/app/assets/javascripts/repository/queries/user_info.query.graphql
@@ -0,0 +1,8 @@
+query getUserInfo {
+ currentUser {
+ id
+ gitpodEnabled
+ preferencesGitpodPath
+ profileEnableGitpodPath
+ }
+}