Welcome to mirror list, hosted at ThFree Co, Russian Federation.

gitlab.com/gitlab-org/gitlab-foss.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
Diffstat (limited to 'app/assets/javascripts/repository')
-rw-r--r--app/assets/javascripts/repository/commits_service.js8
-rw-r--r--app/assets/javascripts/repository/components/blob_button_group.vue6
-rw-r--r--app/assets/javascripts/repository/components/blob_content_viewer.vue55
-rw-r--r--app/assets/javascripts/repository/components/blob_viewers/image_viewer.vue2
-rw-r--r--app/assets/javascripts/repository/components/blob_viewers/index.js6
-rw-r--r--app/assets/javascripts/repository/components/breadcrumbs.vue15
-rw-r--r--app/assets/javascripts/repository/components/delete_blob_modal.vue199
-rw-r--r--app/assets/javascripts/repository/components/last_commit.vue6
-rw-r--r--app/assets/javascripts/repository/components/preview/index.vue1
-rw-r--r--app/assets/javascripts/repository/components/table/header.vue1
-rw-r--r--app/assets/javascripts/repository/components/table/index.vue1
-rw-r--r--app/assets/javascripts/repository/components/table/parent_row.vue6
-rw-r--r--app/assets/javascripts/repository/components/table/row.vue27
-rw-r--r--app/assets/javascripts/repository/components/tree_content.vue4
-rw-r--r--app/assets/javascripts/repository/constants.js4
-rw-r--r--app/assets/javascripts/repository/index.js11
-rw-r--r--app/assets/javascripts/repository/mixins/highlight_mixin.js5
-rw-r--r--app/assets/javascripts/repository/mixins/preload.js2
-rw-r--r--app/assets/javascripts/repository/pages/blob.vue9
-rw-r--r--app/assets/javascripts/repository/pages/index.vue10
-rw-r--r--app/assets/javascripts/repository/pages/tree.vue11
-rw-r--r--app/assets/javascripts/repository/router.js15
-rw-r--r--app/assets/javascripts/repository/utils/ref_switcher_utils.js2
23 files changed, 293 insertions, 113 deletions
diff --git a/app/assets/javascripts/repository/commits_service.js b/app/assets/javascripts/repository/commits_service.js
index e26036b5620..1e0de045d39 100644
--- a/app/assets/javascripts/repository/commits_service.js
+++ b/app/assets/javascripts/repository/commits_service.js
@@ -24,7 +24,7 @@ const addRequestedOffset = (offset) => {
const removeLeadingSlash = (path) => path.replace(/^\//, '');
-const fetchData = (projectPath, path, ref, offset) => {
+const fetchData = (projectPath, path, ref, offset, refType) => {
if (fetchedBatches.includes(offset) || offset < 0) {
return [];
}
@@ -41,12 +41,12 @@ const fetchData = (projectPath, path, ref, offset) => {
);
return axios
- .get(url, { params: { format: 'json', offset } })
+ .get(url, { params: { format: 'json', offset, ref_type: refType } })
.then(({ data }) => normalizeData(data, path))
.catch(() => createAlert({ message: I18N_COMMIT_DATA_FETCH_ERROR }));
};
-export const loadCommits = async (projectPath, path, ref, offset) => {
+export const loadCommits = async (projectPath, path, ref, offset, refType) => {
if (isRequested(offset)) {
return [];
}
@@ -54,7 +54,7 @@ export const loadCommits = async (projectPath, path, ref, offset) => {
// We fetch in batches of 25, so this ensures we don't refetch
Array.from(Array(COMMIT_BATCH_SIZE)).forEach((_, i) => addRequestedOffset(offset + i));
- const commits = await fetchData(projectPath, path, ref, offset);
+ const commits = await fetchData(projectPath, path, ref, offset, refType);
return commits;
};
diff --git a/app/assets/javascripts/repository/components/blob_button_group.vue b/app/assets/javascripts/repository/components/blob_button_group.vue
index d79ccde61a8..99b861ca104 100644
--- a/app/assets/javascripts/repository/components/blob_button_group.vue
+++ b/app/assets/javascripts/repository/components/blob_button_group.vue
@@ -76,6 +76,11 @@ export default {
type: Boolean,
required: true,
},
+ isUsingLfs: {
+ type: Boolean,
+ required: false,
+ default: false,
+ },
},
computed: {
replaceModalTitle() {
@@ -148,6 +153,7 @@ export default {
:can-push-code="canPushCode"
:can-push-to-branch="canPushToBranch"
:empty-repo="emptyRepo"
+ :is-using-lfs="isUsingLfs"
/>
</div>
</template>
diff --git a/app/assets/javascripts/repository/components/blob_content_viewer.vue b/app/assets/javascripts/repository/components/blob_content_viewer.vue
index 969036f84b7..6f9f0a81dfd 100644
--- a/app/assets/javascripts/repository/components/blob_content_viewer.vue
+++ b/app/assets/javascripts/repository/components/blob_content_viewer.vue
@@ -21,7 +21,13 @@ import projectInfoQuery from '../queries/project_info.query.graphql';
import getRefMixin from '../mixins/get_ref';
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, LEGACY_FILE_TYPES } from '../constants';
+import {
+ DEFAULT_BLOB_INFO,
+ TEXT_FILE_TYPE,
+ LFS_STORAGE,
+ LEGACY_FILE_TYPES,
+ CODEOWNERS_FILE_NAME,
+} from '../constants';
import BlobButtonGroup from './blob_button_group.vue';
import ForkSuggestion from './fork_suggestion.vue';
import { loadViewer } from './blob_viewers';
@@ -32,6 +38,7 @@ export default {
BlobButtonGroup,
BlobContent,
GlLoadingIcon,
+ CodeownersValidation: () => import('ee_component/blob/components/codeowners_validation.vue'),
GlButton,
ForkSuggestion,
WebIdeLink,
@@ -76,12 +83,15 @@ export default {
project: {
query: blobInfoQuery,
variables() {
- return {
+ const queryVariables = {
projectPath: this.projectPath,
filePath: this.path,
- ref: this.originalBranch || this.ref,
- shouldFetchRawText: Boolean(this.glFeatures.highlightJs),
+ ref: this.currentRef,
+ refType: this.refType?.toUpperCase() || null,
+ shouldFetchRawText: true,
};
+
+ return queryVariables;
},
result({ data }) {
const blob = data.project?.repository?.blobs?.nodes[0] || {};
@@ -130,6 +140,11 @@ export default {
type: String,
required: true,
},
+ refType: {
+ type: String,
+ required: false,
+ default: null,
+ },
},
data() {
return {
@@ -163,6 +178,12 @@ export default {
return nodes[0] || {};
},
+ currentRef() {
+ return this.originalBranch || this.ref;
+ },
+ isCodeownersFile() {
+ return this.path.includes(CODEOWNERS_FILE_NAME);
+ },
viewer() {
const { richViewer, simpleViewer } = this.blobInfo;
return this.activeViewerType === RICH_BLOB_VIEWER ? richViewer : simpleViewer;
@@ -185,8 +206,7 @@ export default {
);
},
shouldLoadLegacyViewer() {
- const isTextFile = this.viewer.fileType === TEXT_FILE_TYPE && !this.glFeatures.highlightJs;
- return isTextFile || LEGACY_FILE_TYPES.includes(this.blobInfo.fileType) || this.useFallback;
+ return LEGACY_FILE_TYPES.includes(this.blobInfo.fileType) || this.useFallback;
},
legacyViewerLoaded() {
return (
@@ -213,7 +233,9 @@ export default {
const { createMergeRequestIn, forkProject } = this.userPermissions;
const { canModifyBlob } = this.blobInfo;
- return this.isLoggedIn && !canModifyBlob && createMergeRequestIn && forkProject;
+ return (
+ this.isLoggedIn && !this.isUsingLfs && !canModifyBlob && createMergeRequestIn && forkProject
+ );
},
forkPath() {
const forkPaths = {
@@ -259,8 +281,12 @@ export default {
const type = this.activeViewerType;
this.isLoadingLegacyViewer = true;
+
+ const newUrl = new URL(this.blobInfo.webPath, window.location.origin);
+ newUrl.searchParams.set('format', 'json');
+ newUrl.searchParams.set('viewer', type);
axios
- .get(`${this.blobInfo.webPath}?format=json&viewer=${type}`)
+ .get(newUrl.pathname + newUrl.search)
.then(async ({ data: { html, binary } }) => {
this.isRenderingLegacyTextViewer = true;
@@ -343,7 +369,7 @@ export default {
:active-viewer-type="viewer.type"
:has-render-error="hasRenderError"
:show-path="false"
- :override-copy="glFeatures.highlightJs"
+ :override-copy="true"
@viewer-changed="handleViewerChanged"
@copy="onCopy"
>
@@ -382,6 +408,7 @@ export default {
:is-locked="Boolean(pathLockedByUser)"
:can-lock="canLock"
:show-fork-suggestion="showForkSuggestion"
+ :is-using-lfs="isUsingLfs"
@fork="setForkTarget('view')"
/>
</template>
@@ -391,6 +418,12 @@ export default {
:fork-path="forkPath"
@cancel="setForkTarget(null)"
/>
+ <codeowners-validation
+ v-if="isCodeownersFile"
+ :current-ref="currentRef"
+ :project-path="projectPath"
+ :file-path="path"
+ />
<blob-content
v-if="!blobViewer"
class="js-syntax-highlight"
@@ -416,12 +449,12 @@ export default {
:code-navigation-path="blobInfo.codeNavigationPath"
:blob-path="blobInfo.path"
:path-prefix="blobInfo.projectBlobPathRoot"
- :wrap-text-nodes="glFeatures.highlightJs"
+ :wrap-text-nodes="true"
/>
</div>
<ai-genie
v-if="explainCodeAvailable"
- container-id="fileHolder"
+ container-selector=".file-content"
:file-path="path"
class="gl-ml-7"
/>
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 014f1abc121..9a8bb8e4aa6 100644
--- a/app/assets/javascripts/repository/components/blob_viewers/image_viewer.vue
+++ b/app/assets/javascripts/repository/components/blob_viewers/image_viewer.vue
@@ -8,7 +8,7 @@ export default {
},
data() {
return {
- url: this.blob.rawPath,
+ url: this.blob.externalStorageUrl || this.blob.rawPath,
alt: this.blob.name,
};
},
diff --git a/app/assets/javascripts/repository/components/blob_viewers/index.js b/app/assets/javascripts/repository/components/blob_viewers/index.js
index 368f42e0064..d434700b29f 100644
--- a/app/assets/javascripts/repository/components/blob_viewers/index.js
+++ b/app/assets/javascripts/repository/components/blob_viewers/index.js
@@ -1,4 +1,6 @@
-const viewers = {
+import { TEXT_FILE_TYPE, JSON_LANGUAGE } from '../../constants';
+
+export const viewers = {
csv: () => import('./csv_viewer.vue'),
download: () => import('./download_viewer.vue'),
image: () => import('./image_viewer.vue'),
@@ -18,7 +20,7 @@ const viewers = {
export const loadViewer = (type, isUsingLfs, hljsWorkerEnabled, language) => {
let viewer = viewers[type];
- if (hljsWorkerEnabled && language === 'json') {
+ if (hljsWorkerEnabled && language === JSON_LANGUAGE && type === TEXT_FILE_TYPE) {
// The New Source Viewer currently only supports JSON files.
// More language support will be added in: https://gitlab.com/gitlab-org/gitlab/-/issues/415753
viewer = () => import('~/vue_shared/components/source_viewer/source_viewer_new.vue');
diff --git a/app/assets/javascripts/repository/components/breadcrumbs.vue b/app/assets/javascripts/repository/components/breadcrumbs.vue
index d498be0b2bb..b347f97a5ae 100644
--- a/app/assets/javascripts/repository/components/breadcrumbs.vue
+++ b/app/assets/javascripts/repository/components/breadcrumbs.vue
@@ -1,7 +1,8 @@
+<!-- eslint-disable vue/multi-word-component-names -->
<script>
import { GlDisclosureDropdown, GlModalDirective } from '@gitlab/ui';
import permissionsQuery from 'shared_queries/repository/permissions.query.graphql';
-import { joinPaths, escapeFileUrl } from '~/lib/utils/url_utility';
+import { joinPaths, escapeFileUrl, buildURLwithRefType } from '~/lib/utils/url_utility';
import { BV_SHOW_MODAL } from '~/lib/utils/constants';
import { __ } from '~/locale';
import getRefMixin from '../mixins/get_ref';
@@ -49,6 +50,11 @@ export default {
required: false,
default: '',
},
+ refType: {
+ type: String,
+ required: false,
+ default: null,
+ },
canCollaborate: {
type: Boolean,
required: false,
@@ -141,14 +147,17 @@ export default {
return acc.concat({
name,
path,
- to,
+ to: buildURLwithRefType({ path: to, refType: this.refType }),
});
},
[
{
name: this.projectShortPath,
path: '/',
- to: `/-/tree/${this.escapedRef}/`,
+ to: buildURLwithRefType({
+ path: joinPaths('/-/tree', this.escapedRef),
+ refType: this.refType,
+ }),
},
],
);
diff --git a/app/assets/javascripts/repository/components/delete_blob_modal.vue b/app/assets/javascripts/repository/components/delete_blob_modal.vue
index cbdf6ef9ccd..97171a3282b 100644
--- a/app/assets/javascripts/repository/components/delete_blob_modal.vue
+++ b/app/assets/javascripts/repository/components/delete_blob_modal.vue
@@ -1,8 +1,18 @@
<script>
-import { GlModal, GlFormGroup, GlFormInput, GlFormTextarea, GlToggle, GlForm } from '@gitlab/ui';
+import {
+ GlModal,
+ GlFormGroup,
+ GlFormInput,
+ GlFormTextarea,
+ GlToggle,
+ GlForm,
+ GlSprintf,
+ GlLink,
+} from '@gitlab/ui';
import csrf from '~/lib/utils/csrf';
-import { __ } from '~/locale';
+import { __, s__ } from '~/locale';
import validation from '~/vue_shared/directives/validation';
+import { helpPagePath } from '~/helpers/help_page_helper';
import {
SECONDARY_OPTIONS_TEXT,
COMMIT_LABEL,
@@ -28,8 +38,19 @@ export default {
GlFormTextarea,
GlToggle,
GlForm,
+ GlSprintf,
+ GlLink,
},
i18n: {
+ LFS_WARNING_TITLE: __("The file you're about to delete is tracked by LFS"),
+ LFS_WARNING_PRIMARY_CONTENT: s__(
+ 'BlobViewer|If you delete the file, it will be removed from the branch %{branch}.',
+ ),
+ LFS_WARNING_SECONDARY_CONTENT: s__(
+ 'BlobViewer|This file will still take up space in your LFS storage. %{linkStart}How do I remove tracked objects from Git LFS?%{linkEnd}',
+ ),
+ LFS_CONTINUE_TEXT: __('Continue…'),
+ LFS_CANCEL_TEXT: __('Cancel'),
PRIMARY_OPTIONS_TEXT: __('Delete file'),
SECONDARY_OPTIONS_TEXT,
COMMIT_LABEL,
@@ -79,6 +100,11 @@ export default {
type: Boolean,
required: true,
},
+ isUsingLfs: {
+ type: Boolean,
+ required: false,
+ default: false,
+ },
},
data() {
const form = {
@@ -91,6 +117,7 @@ export default {
},
};
return {
+ lfsWarningDismissed: false,
loading: false,
createNewMr: true,
error: '',
@@ -99,7 +126,7 @@ export default {
},
computed: {
primaryOptions() {
- return {
+ const defaultOptions = {
text: this.$options.i18n.PRIMARY_OPTIONS_TEXT,
attributes: {
variant: 'danger',
@@ -107,6 +134,13 @@ export default {
disabled: this.loading || !this.form.state,
},
};
+
+ const lfsWarningOptions = {
+ text: this.$options.i18n.LFS_CONTINUE_TEXT,
+ attributes: { variant: 'confirm' },
+ };
+
+ return this.showLfsWarning ? lfsWarningOptions : defaultOptions;
},
cancelOptions() {
return {
@@ -139,14 +173,39 @@ export default {
(hasFirstLineExceedMaxLength || hasOtherLineExceedMaxLength)
);
},
- /* eslint-enable dot-notation */
+ showLfsWarning() {
+ return this.isUsingLfs && !this.lfsWarningDismissed;
+ },
+ title() {
+ return this.showLfsWarning ? this.$options.i18n.LFS_WARNING_TITLE : this.modalTitle;
+ },
+ showDeleteForm() {
+ return !this.isUsingLfs || (this.isUsingLfs && this.lfsWarningDismissed);
+ },
},
methods: {
show() {
this.$refs[this.modalId].show();
+ this.lfsWarningDismissed = false;
+ },
+ cancel() {
+ this.$refs[this.modalId].hide();
},
- submitForm(e) {
+ async handleContinueLfsWarning() {
+ this.lfsWarningDismissed = true;
+ await this.$nextTick();
+ this.$refs.message?.$el.focus();
+ },
+ async handlePrimaryAction(e) {
e.preventDefault(); // Prevent modal from closing
+
+ if (this.showLfsWarning) {
+ this.lfsWarningDismissed = true;
+ await this.$nextTick();
+ this.$refs.message?.$el.focus();
+ return;
+ }
+
this.form.showValidation = true;
if (!this.form.state) {
@@ -158,6 +217,7 @@ export default {
this.$refs.form.$el.submit();
},
},
+ deleteLfsHelpPath: helpPagePath('topics/git/lfs/index', { anchor: 'removing-objects-from-lfs' }),
};
</script>
@@ -165,67 +225,86 @@ export default {
<gl-modal
:ref="modalId"
v-bind="$attrs"
- data-testid="modal-delete"
:modal-id="modalId"
- :title="modalTitle"
+ :title="title"
:action-primary="primaryOptions"
:action-cancel="cancelOptions"
- @primary="submitForm"
+ @primary="handlePrimaryAction"
>
- <gl-form ref="form" novalidate :action="deletePath" method="post">
- <input type="hidden" name="_method" value="delete" />
- <input :value="$options.csrf.token" type="hidden" name="authenticity_token" />
- <template v-if="emptyRepo">
- <input type="hidden" name="branch_name" :value="originalBranch" class="js-branch-name" />
- </template>
- <template v-else>
- <input type="hidden" name="original_branch" :value="originalBranch" />
- <input
- v-if="createNewMr || !canPushToBranch"
- type="hidden"
- name="create_merge_request"
- value="1"
- />
- <gl-form-group
- :label="$options.i18n.COMMIT_LABEL"
- label-for="commit_message"
- :invalid-feedback="form.fields['commit_message'].feedback"
- >
- <gl-form-textarea
- v-model="form.fields['commit_message'].value"
- v-validation:[form.showValidation]
- name="commit_message"
- data-qa-selector="commit_message_field"
- :state="form.fields['commit_message'].state"
- :disabled="loading"
- required
+ <div v-if="showLfsWarning">
+ <p>
+ <gl-sprintf :message="$options.i18n.LFS_WARNING_PRIMARY_CONTENT">
+ <template #branch>
+ <code>{{ targetBranch }}</code>
+ </template>
+ </gl-sprintf>
+ </p>
+
+ <p>
+ <gl-sprintf :message="$options.i18n.LFS_WARNING_SECONDARY_CONTENT">
+ <template #link="{ content }">
+ <gl-link :href="$options.deleteLfsHelpPath">{{ content }}</gl-link>
+ </template>
+ </gl-sprintf>
+ </p>
+ </div>
+ <div v-if="showDeleteForm">
+ <gl-form ref="form" novalidate :action="deletePath" method="post">
+ <input type="hidden" name="_method" value="delete" />
+ <input :value="$options.csrf.token" type="hidden" name="authenticity_token" />
+ <template v-if="emptyRepo">
+ <input type="hidden" name="branch_name" :value="originalBranch" class="js-branch-name" />
+ </template>
+ <template v-else>
+ <input type="hidden" name="original_branch" :value="originalBranch" />
+ <input
+ v-if="createNewMr || !canPushToBranch"
+ type="hidden"
+ name="create_merge_request"
+ value="1"
/>
- <p v-if="showHint" class="form-text gl-text-gray-600" data-testid="hint">
- {{ $options.i18n.COMMIT_MESSAGE_HINT }}
- </p>
- </gl-form-group>
- <gl-form-group
- v-if="canPushCode"
- :label="$options.i18n.TARGET_BRANCH_LABEL"
- label-for="branch_name"
- :invalid-feedback="form.fields['branch_name'].feedback"
- >
- <gl-form-input
- v-model="form.fields['branch_name'].value"
- v-validation:[form.showValidation]
- :state="form.fields['branch_name'].state"
+ <gl-form-group
+ :label="$options.i18n.COMMIT_LABEL"
+ label-for="commit_message"
+ :invalid-feedback="form.fields['commit_message'].feedback"
+ >
+ <gl-form-textarea
+ ref="message"
+ v-model="form.fields['commit_message'].value"
+ v-validation:[form.showValidation]
+ name="commit_message"
+ data-qa-selector="commit_message_field"
+ :state="form.fields['commit_message'].state"
+ :disabled="loading"
+ required
+ />
+ <p v-if="showHint" class="form-text gl-text-gray-600" data-testid="hint">
+ {{ $options.i18n.COMMIT_MESSAGE_HINT }}
+ </p>
+ </gl-form-group>
+ <gl-form-group
+ v-if="canPushCode"
+ :label="$options.i18n.TARGET_BRANCH_LABEL"
+ label-for="branch_name"
+ :invalid-feedback="form.fields['branch_name'].feedback"
+ >
+ <gl-form-input
+ v-model="form.fields['branch_name'].value"
+ v-validation:[form.showValidation]
+ :state="form.fields['branch_name'].state"
+ :disabled="loading"
+ name="branch_name"
+ required
+ />
+ </gl-form-group>
+ <gl-toggle
+ v-if="showCreateNewMrToggle"
+ v-model="createNewMr"
:disabled="loading"
- name="branch_name"
- required
+ :label="$options.i18n.TOGGLE_CREATE_MR_LABEL"
/>
- </gl-form-group>
- <gl-toggle
- v-if="showCreateNewMrToggle"
- v-model="createNewMr"
- :disabled="loading"
- :label="$options.i18n.TOGGLE_CREATE_MR_LABEL"
- />
- </template>
- </gl-form>
+ </template>
+ </gl-form>
+ </div>
</gl-modal>
</template>
diff --git a/app/assets/javascripts/repository/components/last_commit.vue b/app/assets/javascripts/repository/components/last_commit.vue
index bdc9ed210ed..fa51ef30546 100644
--- a/app/assets/javascripts/repository/components/last_commit.vue
+++ b/app/assets/javascripts/repository/components/last_commit.vue
@@ -43,6 +43,7 @@ export default {
return {
projectPath: this.projectPath,
ref: this.ref,
+ refType: this.refType?.toUpperCase(),
path: this.currentPath.replace(/^\//, ''),
};
},
@@ -69,6 +70,11 @@ export default {
required: false,
default: '',
},
+ refType: {
+ type: String,
+ required: false,
+ default: null,
+ },
},
data() {
return {
diff --git a/app/assets/javascripts/repository/components/preview/index.vue b/app/assets/javascripts/repository/components/preview/index.vue
index 90949536cc1..bdcacd80b30 100644
--- a/app/assets/javascripts/repository/components/preview/index.vue
+++ b/app/assets/javascripts/repository/components/preview/index.vue
@@ -1,3 +1,4 @@
+<!-- eslint-disable vue/multi-word-component-names -->
<script>
import { GlIcon, GlLink, GlLoadingIcon } from '@gitlab/ui';
import SafeHtml from '~/vue_shared/directives/safe_html';
diff --git a/app/assets/javascripts/repository/components/table/header.vue b/app/assets/javascripts/repository/components/table/header.vue
index 9d30aa88155..f99cfea2e6e 100644
--- a/app/assets/javascripts/repository/components/table/header.vue
+++ b/app/assets/javascripts/repository/components/table/header.vue
@@ -1,3 +1,4 @@
+<!-- eslint-disable vue/multi-word-component-names -->
<template>
<thead>
<tr>
diff --git a/app/assets/javascripts/repository/components/table/index.vue b/app/assets/javascripts/repository/components/table/index.vue
index 46d546c2ee4..557e9cd168f 100644
--- a/app/assets/javascripts/repository/components/table/index.vue
+++ b/app/assets/javascripts/repository/components/table/index.vue
@@ -1,3 +1,4 @@
+<!-- eslint-disable vue/multi-word-component-names -->
<script>
import { GlSkeletonLoader, GlButton } from '@gitlab/ui';
import { sprintf, __ } from '~/locale';
diff --git a/app/assets/javascripts/repository/components/table/parent_row.vue b/app/assets/javascripts/repository/components/table/parent_row.vue
index 8a081944600..0bc22253bd2 100644
--- a/app/assets/javascripts/repository/components/table/parent_row.vue
+++ b/app/assets/javascripts/repository/components/table/parent_row.vue
@@ -1,5 +1,6 @@
<script>
import { GlLoadingIcon, GlTooltipDirective } from '@gitlab/ui';
+import { joinPaths, buildURLwithRefType } from '~/lib/utils/url_utility';
export default {
components: {
@@ -8,6 +9,7 @@ export default {
directives: {
GlTooltip: GlTooltipDirective,
},
+ inject: ['refType'],
props: {
commitRef: {
type: String,
@@ -31,7 +33,9 @@ export default {
return splitArray.map((p) => encodeURIComponent(p)).join('/');
},
parentRoute() {
- return { path: `/-/tree/${this.commitRef}/${this.parentPath}` };
+ const path = joinPaths('/-/tree', this.commitRef, this.parentPath);
+
+ return buildURLwithRefType({ path, refType: this.refType });
},
},
methods: {
diff --git a/app/assets/javascripts/repository/components/table/row.vue b/app/assets/javascripts/repository/components/table/row.vue
index 6dd059a349f..c839d7a53cd 100644
--- a/app/assets/javascripts/repository/components/table/row.vue
+++ b/app/assets/javascripts/repository/components/table/row.vue
@@ -1,3 +1,4 @@
+<!-- eslint-disable vue/multi-word-component-names -->
<script>
import {
GlBadge,
@@ -12,11 +13,10 @@ import {
import { escapeRegExp } from 'lodash';
import SafeHtml from '~/vue_shared/directives/safe_html';
import paginatedTreeQuery from 'shared_queries/repository/paginated_tree.query.graphql';
-import { escapeFileUrl } from '~/lib/utils/url_utility';
+import { buildURLwithRefType, joinPaths } from '~/lib/utils/url_utility';
import { TREE_PAGE_SIZE, ROW_APPEAR_DELAY } from '~/repository/constants';
import FileIcon from '~/vue_shared/components/file_icon.vue';
import TimeagoTooltip from '~/vue_shared/components/time_ago_tooltip.vue';
-import glFeatureFlagMixin from '~/vue_shared/mixins/gl_feature_flags_mixin';
import blobInfoQuery from 'shared_queries/repository/blob_info.query.graphql';
import getRefMixin from '../../mixins/get_ref';
@@ -36,7 +36,8 @@ export default {
GlHoverLoad: GlHoverLoadDirective,
SafeHtml,
},
- mixins: [getRefMixin, glFeatureFlagMixin()],
+ mixins: [getRefMixin],
+ inject: ['refType'],
props: {
commitInfo: {
type: Object,
@@ -117,14 +118,18 @@ export default {
return this.commitInfo;
},
routerLinkTo() {
- const blobRouteConfig = { path: `/-/blob/${this.escapedRef}/${escapeFileUrl(this.path)}` };
- const treeRouteConfig = { path: `/-/tree/${this.escapedRef}/${escapeFileUrl(this.path)}` };
-
if (this.isBlob) {
- return blobRouteConfig;
+ return buildURLwithRefType({
+ path: joinPaths('/-/blob', this.escapedRef, this.path),
+ refType: this.refType,
+ });
+ } else if (this.isFolder) {
+ return buildURLwithRefType({
+ path: joinPaths('/-/tree', this.escapedRef, this.path),
+ refType: this.refType,
+ });
}
-
- return this.isFolder ? treeRouteConfig : null;
+ return null;
},
isBlob() {
return this.type === 'blob';
@@ -159,6 +164,7 @@ export default {
this.apolloQuery(paginatedTreeQuery, {
projectPath: this.projectPath,
ref: this.ref,
+ refType: this.refType?.toUpperCase() || null,
path: this.path,
nextPageCursor: '',
pageSize: TREE_PAGE_SIZE,
@@ -169,7 +175,8 @@ export default {
projectPath: this.projectPath,
filePath: this.path,
ref: this.ref,
- shouldFetchRawText: Boolean(this.glFeatures.highlightJs),
+ refType: this.refType?.toUpperCase() || null,
+ shouldFetchRawText: true,
});
},
apolloQuery(query, variables) {
diff --git a/app/assets/javascripts/repository/components/tree_content.vue b/app/assets/javascripts/repository/components/tree_content.vue
index 0c9b46344c5..dd2cfddc94e 100644
--- a/app/assets/javascripts/repository/components/tree_content.vue
+++ b/app/assets/javascripts/repository/components/tree_content.vue
@@ -27,6 +27,7 @@ export default {
query: projectPathQuery,
},
},
+ inject: ['refType'],
props: {
path: {
type: String,
@@ -99,6 +100,7 @@ export default {
variables: {
projectPath: this.projectPath,
ref: this.ref,
+ refType: this.refType?.toUpperCase(),
path: originalPath,
nextPageCursor: this.nextPageCursor,
pageSize: TREE_PAGE_SIZE,
@@ -171,7 +173,7 @@ export default {
}
},
loadCommitData(rowNumber) {
- loadCommits(this.projectPath, this.path, this.ref, rowNumber)
+ loadCommits(this.projectPath, this.path, this.ref, rowNumber, this.refType)
.then(this.setCommitData)
.catch(() => {});
},
diff --git a/app/assets/javascripts/repository/constants.js b/app/assets/javascripts/repository/constants.js
index b711f671850..3079ef0bfbb 100644
--- a/app/assets/javascripts/repository/constants.js
+++ b/app/assets/javascripts/repository/constants.js
@@ -83,6 +83,8 @@ export const DEFAULT_BLOB_INFO = {
},
};
+export const JSON_LANGUAGE = 'json';
+export const OPENAPI_FILE_TYPE = 'openapi';
export const TEXT_FILE_TYPE = 'text';
export const LFS_STORAGE = 'lfs';
@@ -114,3 +116,5 @@ export const POLLING_INTERVAL_BACKOFF = 2;
export const CONFLICTS_MODAL_ID = 'fork-sync-conflicts-modal';
export const FORK_UPDATED_EVENT = 'fork:updated';
+
+export const CODEOWNERS_FILE_NAME = 'CODEOWNERS';
diff --git a/app/assets/javascripts/repository/index.js b/app/assets/javascripts/repository/index.js
index c1e0104c6ac..9753173ac30 100644
--- a/app/assets/javascripts/repository/index.js
+++ b/app/assets/javascripts/repository/index.js
@@ -1,5 +1,6 @@
import { GlButton } from '@gitlab/ui';
import Vue from 'vue';
+// eslint-disable-next-line no-restricted-imports
import Vuex from 'vuex';
import { parseBoolean } from '~/lib/utils/common_utils';
import { joinPaths, escapeFileUrl, visitUrl } from '~/lib/utils/url_utility';
@@ -121,6 +122,7 @@ export default function setupVueRepositoryList() {
return h(LastCommit, {
props: {
currentPath: this.$route.params.path,
+ refType: this.$route.query.ref_type,
},
});
},
@@ -207,6 +209,7 @@ export default function setupVueRepositoryList() {
return h(Breadcrumbs, {
props: {
currentPath: this.$route.params.path,
+ refType: this.$route.query.ref_type,
canCollaborate: parseBoolean(canCollaborate),
canEditTree: parseBoolean(canEditTree),
canPushCode: parseBoolean(canPushCode),
@@ -228,20 +231,12 @@ export default function setupVueRepositoryList() {
const treeHistoryLinkEl = document.getElementById('js-tree-history-link');
const { historyLink } = treeHistoryLinkEl.dataset;
- let { isProjectOverview } = treeHistoryLinkEl.dataset;
-
- const isProjectOverviewAfterEach = router.afterEach(() => {
- isProjectOverview = false;
- isProjectOverviewAfterEach();
- });
// eslint-disable-next-line no-new
new Vue({
el: treeHistoryLinkEl,
router,
render(h) {
- if (parseBoolean(isProjectOverview) && !this.$route.params.path) return null;
-
return h(
GlButton,
{
diff --git a/app/assets/javascripts/repository/mixins/highlight_mixin.js b/app/assets/javascripts/repository/mixins/highlight_mixin.js
index 822a8b4ee38..5b6f68681bb 100644
--- a/app/assets/javascripts/repository/mixins/highlight_mixin.js
+++ b/app/assets/javascripts/repository/mixins/highlight_mixin.js
@@ -8,7 +8,6 @@ import { splitIntoChunks } from '~/vue_shared/components/source_viewer/workers/h
import LineHighlighter from '~/blob/line_highlighter';
import languageLoader from '~/content_editor/services/highlight_js_language_loader';
import Tracking from '~/tracking';
-import { TEXT_FILE_TYPE } from '../constants';
/*
* This mixin is intended to be used as an interface between our highlight worker and Vue components
@@ -37,8 +36,8 @@ export default {
this.trackEvent(EVENT_LABEL_FALLBACK, language);
this?.onError();
},
- initHighlightWorker({ rawTextBlob, language, simpleViewer, fileType }) {
- if (simpleViewer?.fileType !== TEXT_FILE_TYPE || !this.glFeatures.highlightJsWorker) return;
+ initHighlightWorker({ rawTextBlob, language, fileType }) {
+ if (language !== 'json' || !this.glFeatures.highlightJsWorker) return;
if (this.isUnsupportedLanguage(language)) {
this.handleUnsupportedLanguage(language);
diff --git a/app/assets/javascripts/repository/mixins/preload.js b/app/assets/javascripts/repository/mixins/preload.js
index 30c36dee48f..473317ecf5d 100644
--- a/app/assets/javascripts/repository/mixins/preload.js
+++ b/app/assets/javascripts/repository/mixins/preload.js
@@ -18,13 +18,13 @@ export default {
methods: {
preload(path = '/', next) {
this.loadingPath = path.replace(/^\//, '');
-
return this.$apollo
.query({
query: paginatedTreeQuery,
variables: {
projectPath: this.projectPath,
ref: this.ref,
+ refType: this.refType?.toUpperCase(),
path: this.loadingPath,
nextPageCursor: '',
pageSize: 100,
diff --git a/app/assets/javascripts/repository/pages/blob.vue b/app/assets/javascripts/repository/pages/blob.vue
index c09e2133936..89bfba79a37 100644
--- a/app/assets/javascripts/repository/pages/blob.vue
+++ b/app/assets/javascripts/repository/pages/blob.vue
@@ -1,3 +1,4 @@
+<!-- eslint-disable vue/multi-word-component-names -->
<script>
// This file is in progress and behind a feature flag, please see the following issue for more:
// https://gitlab.com/gitlab-org/gitlab/-/issues/323200
@@ -31,11 +32,15 @@ export default {
type: String,
required: true,
},
+ refType: {
+ type: String,
+ required: false,
+ default: null,
+ },
},
limitedContainerElements: document.querySelectorAll(`.${LIMITED_CONTAINER_WIDTH_CLASS}`),
};
</script>
-
<template>
- <blob-content-viewer :path="path" :project-path="projectPath" />
+ <blob-content-viewer :path="path" :project-path="projectPath" :ref-type="refType" />
</template>
diff --git a/app/assets/javascripts/repository/pages/index.vue b/app/assets/javascripts/repository/pages/index.vue
index 0e53235779c..0e46871cee1 100644
--- a/app/assets/javascripts/repository/pages/index.vue
+++ b/app/assets/javascripts/repository/pages/index.vue
@@ -1,3 +1,4 @@
+<!-- eslint-disable vue/multi-word-component-names -->
<script>
import { updateElementsVisibility } from '../utils/dom';
import TreePage from './tree.vue';
@@ -6,6 +7,13 @@ export default {
components: {
TreePage,
},
+ props: {
+ refType: {
+ type: String,
+ required: false,
+ default: null,
+ },
+ },
mounted() {
this.updateProjectElements(true);
},
@@ -21,5 +29,5 @@ export default {
</script>
<template>
- <tree-page path="/" />
+ <tree-page path="/" :ref-type="refType" />
</template>
diff --git a/app/assets/javascripts/repository/pages/tree.vue b/app/assets/javascripts/repository/pages/tree.vue
index 6bf674eb3f1..0d35bfa679f 100644
--- a/app/assets/javascripts/repository/pages/tree.vue
+++ b/app/assets/javascripts/repository/pages/tree.vue
@@ -1,3 +1,4 @@
+<!-- eslint-disable vue/multi-word-component-names -->
<script>
import TreeContent from 'jh_else_ce/repository/components/tree_content.vue';
import preloadMixin from '../mixins/preload';
@@ -8,12 +9,22 @@ export default {
TreeContent,
},
mixins: [preloadMixin],
+ provide() {
+ return {
+ refType: this.refType,
+ };
+ },
props: {
path: {
type: String,
required: false,
default: '/',
},
+ refType: {
+ type: String,
+ required: false,
+ default: '',
+ },
},
computed: {
isRoot() {
diff --git a/app/assets/javascripts/repository/router.js b/app/assets/javascripts/repository/router.js
index 0a675e14eb5..5f73912ed2b 100644
--- a/app/assets/javascripts/repository/router.js
+++ b/app/assets/javascripts/repository/router.js
@@ -13,15 +13,19 @@ export default function createRouter(base, baseRef) {
component: TreePage,
props: (route) => ({
path: route.params.path?.replace(/^\//, '') || '/',
+ refType: route.query.ref_type || null,
}),
};
const blobPathRoute = {
component: BlobPage,
- props: (route) => ({
- path: route.params.path,
- projectPath: base,
- }),
+ props: (route) => {
+ return {
+ path: route.params.path,
+ projectPath: base,
+ refType: route.query.ref_type || null,
+ };
+ },
};
const router = new VueRouter({
@@ -56,6 +60,9 @@ export default function createRouter(base, baseRef) {
path: '/',
name: 'projectRoot',
component: IndexPage,
+ props: {
+ refType: 'HEADS',
+ },
},
],
});
diff --git a/app/assets/javascripts/repository/utils/ref_switcher_utils.js b/app/assets/javascripts/repository/utils/ref_switcher_utils.js
index bcad4a2c822..f3d21971771 100644
--- a/app/assets/javascripts/repository/utils/ref_switcher_utils.js
+++ b/app/assets/javascripts/repository/utils/ref_switcher_utils.js
@@ -28,7 +28,7 @@ export function generateRefDestinationPath(projectRootPath, ref, selectedRef) {
[, refType, actualRef] = matches;
}
if (refType) {
- url.searchParams.set('ref_type', refType);
+ url.searchParams.set('ref_type', refType.toLowerCase());
} else {
url.searchParams.delete('ref_type');
}