diff options
author | GitLab Bot <gitlab-bot@gitlab.com> | 2021-06-16 18:25:58 +0000 |
---|---|---|
committer | GitLab Bot <gitlab-bot@gitlab.com> | 2021-06-16 18:25:58 +0000 |
commit | a5f4bba440d7f9ea47046a0a561d49adf0a1e6d4 (patch) | |
tree | fb69158581673816a8cd895f9d352dcb3c678b1e /app/assets/javascripts/repository/components | |
parent | d16b2e8639e99961de6ddc93909f3bb5c1445ba1 (diff) | |
download | gitlab-ce-a5f4bba440d7f9ea47046a0a561d49adf0a1e6d4.tar.gz |
Add latest changes from gitlab-org/gitlab@14-0-stable-eev14.0.0-rc42
Diffstat (limited to 'app/assets/javascripts/repository/components')
7 files changed, 224 insertions, 37 deletions
diff --git a/app/assets/javascripts/repository/components/blob_content_viewer.vue b/app/assets/javascripts/repository/components/blob_content_viewer.vue index a9701c8f8aa..7fbf331d585 100644 --- a/app/assets/javascripts/repository/components/blob_content_viewer.vue +++ b/app/assets/javascripts/repository/components/blob_content_viewer.vue @@ -8,11 +8,13 @@ import createFlash from '~/flash'; import { __ } from '~/locale'; import blobInfoQuery from '../queries/blob_info.query.graphql'; import BlobHeaderEdit from './blob_header_edit.vue'; +import BlobReplace from './blob_replace.vue'; export default { components: { BlobHeader, BlobHeaderEdit, + BlobReplace, BlobContent, GlLoadingIcon, }, @@ -87,6 +89,9 @@ export default { }; }, computed: { + isLoggedIn() { + return Boolean(gon.current_user_id); + }, isLoading() { return this.$apollo.queries.project.loading; }, @@ -126,7 +131,17 @@ export default { @viewer-changed="switchViewer" > <template #actions> - <blob-header-edit :edit-path="blobInfo.editBlobPath" /> + <blob-header-edit + :edit-path="blobInfo.editBlobPath" + :web-ide-path="blobInfo.ideEditPath" + /> + <blob-replace + v-if="isLoggedIn" + :path="path" + :name="blobInfo.name" + :replace-path="blobInfo.replacePath" + :can-push-code="blobInfo.canModifyBlob" + /> </template> </blob-header> <blob-content diff --git a/app/assets/javascripts/repository/components/blob_header_edit.vue b/app/assets/javascripts/repository/components/blob_header_edit.vue index f3649895736..3d97ebe89e4 100644 --- a/app/assets/javascripts/repository/components/blob_header_edit.vue +++ b/app/assets/javascripts/repository/components/blob_header_edit.vue @@ -1,25 +1,47 @@ <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: { editPath: { type: String, required: true, }, + webIdePath: { + type: String, + required: true, + }, }, }; </script> <template> - <gl-button category="primary" variant="confirm" class="gl-mr-3" :href="editPath"> - {{ $options.i18n.edit }} - </gl-button> + <web-ide-link + v-if="glFeatures.consolidatedEditButton" + class="gl-mr-3" + :edit-url="editPath" + :web-ide-url="webIdePath" + :is-blob="true" + /> + <div v-else> + <gl-button class="gl-mr-2" category="primary" variant="confirm" :href="editPath"> + {{ $options.i18n.edit }} + </gl-button> + + <gl-button class="gl-mr-3" category="primary" variant="confirm" :href="webIdePath"> + {{ $options.i18n.webIde }} + </gl-button> + </div> </template> diff --git a/app/assets/javascripts/repository/components/blob_replace.vue b/app/assets/javascripts/repository/components/blob_replace.vue new file mode 100644 index 00000000000..91d7811eb6d --- /dev/null +++ b/app/assets/javascripts/repository/components/blob_replace.vue @@ -0,0 +1,75 @@ +<script> +import { GlButton, GlModalDirective } from '@gitlab/ui'; +import { uniqueId } from 'lodash'; +import { sprintf, __ } from '~/locale'; +import getRefMixin from '../mixins/get_ref'; +import UploadBlobModal from './upload_blob_modal.vue'; + +export default { + i18n: { + replace: __('Replace'), + replacePrimaryBtnText: __('Replace file'), + }, + components: { + GlButton, + UploadBlobModal, + }, + directives: { + GlModal: GlModalDirective, + }, + mixins: [getRefMixin], + inject: { + targetBranch: { + default: '', + }, + originalBranch: { + default: '', + }, + }, + props: { + name: { + type: String, + required: true, + }, + path: { + type: String, + required: true, + }, + replacePath: { + type: String, + required: true, + }, + canPushCode: { + type: Boolean, + required: true, + }, + }, + computed: { + replaceModalId() { + return uniqueId('replace-modal'); + }, + title() { + return sprintf(__('Replace %{name}'), { name: this.name }); + }, + }, +}; +</script> + +<template> + <div class="gl-mr-3"> + <gl-button v-gl-modal="replaceModalId"> + {{ $options.i18n.replace }} + </gl-button> + <upload-blob-modal + :modal-id="replaceModalId" + :modal-title="title" + :commit-message="title" + :target-branch="targetBranch || ref" + :original-branch="originalBranch || ref" + :can-push-code="canPushCode" + :path="path" + :replace-path="replacePath" + :primary-btn-text="$options.i18n.replacePrimaryBtnText" + /> + </div> +</template> diff --git a/app/assets/javascripts/repository/components/table/index.vue b/app/assets/javascripts/repository/components/table/index.vue index 22dffb7d2db..ca5711de49c 100644 --- a/app/assets/javascripts/repository/components/table/index.vue +++ b/app/assets/javascripts/repository/components/table/index.vue @@ -51,6 +51,9 @@ export default { }; }, computed: { + totalEntries() { + return Object.values(this.entries).flat().length; + }, tableCaption() { if (this.isLoading) { return sprintf( @@ -111,6 +114,7 @@ export default { :submodule-tree-url="entry.treeUrl" :lfs-oid="entry.lfsOid" :loading-path="loadingPath" + :total-entries="totalEntries" /> </template> <template v-if="isLoading"> diff --git a/app/assets/javascripts/repository/components/table/row.vue b/app/assets/javascripts/repository/components/table/row.vue index 8ea5fce92fa..62f863db871 100644 --- a/app/assets/javascripts/repository/components/table/row.vue +++ b/app/assets/javascripts/repository/components/table/row.vue @@ -7,13 +7,17 @@ import { GlTooltipDirective, GlLoadingIcon, GlIcon, + GlHoverLoadDirective, } from '@gitlab/ui'; import { escapeRegExp } from 'lodash'; +import filesQuery from 'shared_queries/repository/files.query.graphql'; import { escapeFileUrl } from '~/lib/utils/url_utility'; +import { TREE_PAGE_SIZE } 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 getRefMixin from '../../mixins/get_ref'; +import blobInfoQuery from '../../queries/blob_info.query.graphql'; import commitQuery from '../../queries/commit.query.graphql'; export default { @@ -28,6 +32,7 @@ export default { }, directives: { GlTooltip: GlTooltipDirective, + GlHoverLoad: GlHoverLoadDirective, }, apollo: { commit: { @@ -38,12 +43,17 @@ export default { type: this.type, path: this.currentPath, projectPath: this.projectPath, + maxOffset: this.totalEntries, }; }, }, }, mixins: [getRefMixin, glFeatureFlagMixin()], props: { + totalEntries: { + type: Number, + required: true, + }, id: { type: String, required: true, @@ -139,6 +149,33 @@ export default { return this.commit && this.commit.lockLabel; }, }, + methods: { + handlePreload() { + return this.isFolder ? this.loadFolder() : this.loadBlob(); + }, + loadFolder() { + this.apolloQuery(filesQuery, { + projectPath: this.projectPath, + ref: this.ref, + path: this.path, + nextPageCursor: '', + pageSize: TREE_PAGE_SIZE, + }); + }, + loadBlob() { + if (!this.refactorBlobViewerEnabled) { + return; + } + + this.apolloQuery(blobInfoQuery, { + projectPath: this.projectPath, + filePath: this.path, + }); + }, + apolloQuery(query, variables) { + this.$apollo.query({ query, variables }); + }, + }, }; </script> @@ -148,6 +185,7 @@ export default { <component :is="linkComponent" ref="link" + v-gl-hover-load="handlePreload" :to="routerLinkTo" :href="url" :class="{ diff --git a/app/assets/javascripts/repository/components/tree_content.vue b/app/assets/javascripts/repository/components/tree_content.vue index 336237abd8a..794a8a85cc5 100644 --- a/app/assets/javascripts/repository/components/tree_content.vue +++ b/app/assets/javascripts/repository/components/tree_content.vue @@ -1,17 +1,14 @@ <script> import filesQuery from 'shared_queries/repository/files.query.graphql'; -import { deprecatedCreateFlash as createFlash } from '~/flash'; +import createFlash from '~/flash'; import { __ } from '../../locale'; +import { TREE_PAGE_SIZE, TREE_INITIAL_FETCH_COUNT } from '../constants'; import getRefMixin from '../mixins/get_ref'; import projectPathQuery from '../queries/project_path.query.graphql'; import { readmeFile } from '../utils/readme'; import FilePreview from './preview/index.vue'; import FileTable from './table/index.vue'; -const LIMIT = 1000; -const PAGE_SIZE = 100; -export const INITIAL_FETCH_COUNT = LIMIT / PAGE_SIZE; - export default { components: { FileTable, @@ -47,7 +44,7 @@ export default { isLoadingFiles: false, isOverLimit: false, clickedShowMore: false, - pageSize: PAGE_SIZE, + pageSize: TREE_PAGE_SIZE, fetchCounter: 0, }; }, @@ -56,7 +53,7 @@ export default { return readmeFile(this.entries.blobs); }, hasShowMore() { - return !this.clickedShowMore && this.fetchCounter === INITIAL_FETCH_COUNT; + return !this.clickedShowMore && this.fetchCounter === TREE_INITIAL_FETCH_COUNT; }, }, @@ -107,14 +104,16 @@ export default { if (pageInfo?.hasNextPage) { this.nextPageCursor = pageInfo.endCursor; this.fetchCounter += 1; - if (this.fetchCounter < INITIAL_FETCH_COUNT || this.clickedShowMore) { + if (this.fetchCounter < TREE_INITIAL_FETCH_COUNT || this.clickedShowMore) { this.fetchFiles(); this.clickedShowMore = false; } } }) .catch((error) => { - createFlash(__('An error occurred while fetching folder content.')); + createFlash({ + message: __('An error occurred while fetching folder content.'), + }); throw error; }); }, diff --git a/app/assets/javascripts/repository/components/upload_blob_modal.vue b/app/assets/javascripts/repository/components/upload_blob_modal.vue index aa087d4c631..7f065dbdf6d 100644 --- a/app/assets/javascripts/repository/components/upload_blob_modal.vue +++ b/app/assets/javascripts/repository/components/upload_blob_modal.vue @@ -43,7 +43,6 @@ export default { GlAlert, }, i18n: { - MODAL_TITLE, COMMIT_LABEL, TARGET_BRANCH_LABEL, TOGGLE_CREATE_MR_LABEL, @@ -51,6 +50,16 @@ export default { NEW_BRANCH_IN_FORK, }, props: { + modalTitle: { + type: String, + default: MODAL_TITLE, + required: false, + }, + primaryBtnText: { + type: String, + default: PRIMARY_OPTIONS_TEXT, + required: false, + }, modalId: { type: String, required: true, @@ -75,6 +84,11 @@ export default { type: String, required: true, }, + replacePath: { + type: String, + default: null, + required: false, + }, }, data() { return { @@ -90,7 +104,7 @@ export default { computed: { primaryOptions() { return { - text: PRIMARY_OPTIONS_TEXT, + text: this.primaryBtnText, attributes: [ { variant: 'confirm', @@ -136,6 +150,45 @@ export default { this.file = null; this.filePreviewURL = null; }, + submitForm() { + return this.replacePath ? this.replaceFile() : this.uploadFile(); + }, + submitRequest(method, url) { + return axios({ + method, + url, + data: this.formData(), + headers: { + ...ContentTypeMultipartFormData, + }, + }) + .then((response) => { + if (!this.replacePath) { + trackFileUploadEvent('click_upload_modal_form_submit'); + } + visitUrl(response.data.filePath); + }) + .catch(() => { + this.loading = false; + createFlash(ERROR_MESSAGE); + }); + }, + formData() { + const formData = new FormData(); + formData.append('branch_name', this.target); + formData.append('create_merge_request', this.createNewMr); + formData.append('commit_message', this.commit); + formData.append('file', this.file); + + return formData; + }, + replaceFile() { + this.loading = true; + + // The PUT path can be geneated from $route (similar to "uploadFile") once router is connected + // Follow-up issue: https://gitlab.com/gitlab-org/gitlab/-/issues/332736 + return this.submitRequest('put', this.replacePath); + }, uploadFile() { this.loading = true; @@ -146,26 +199,7 @@ export default { } = this; const uploadPath = joinPaths(this.path, path); - const formData = new FormData(); - formData.append('branch_name', this.target); - formData.append('create_merge_request', this.createNewMr); - formData.append('commit_message', this.commit); - formData.append('file', this.file); - - return axios - .post(uploadPath, formData, { - headers: { - ...ContentTypeMultipartFormData, - }, - }) - .then((response) => { - trackFileUploadEvent('click_upload_modal_form_submit'); - visitUrl(response.data.filePath); - }) - .catch(() => { - this.loading = false; - createFlash(ERROR_MESSAGE); - }); + return this.submitRequest('post', uploadPath); }, }, validFileMimetypes: [], @@ -175,10 +209,10 @@ export default { <gl-form> <gl-modal :modal-id="modalId" - :title="$options.i18n.MODAL_TITLE" + :title="modalTitle" :action-primary="primaryOptions" :action-cancel="cancelOptions" - @primary.prevent="uploadFile" + @primary.prevent="submitForm" > <upload-dropzone class="gl-h-200! gl-mb-4" |