summaryrefslogtreecommitdiff
path: root/app/assets/javascripts/repository/components/upload_blob_modal.vue
diff options
context:
space:
mode:
Diffstat (limited to 'app/assets/javascripts/repository/components/upload_blob_modal.vue')
-rw-r--r--app/assets/javascripts/repository/components/upload_blob_modal.vue220
1 files changed, 220 insertions, 0 deletions
diff --git a/app/assets/javascripts/repository/components/upload_blob_modal.vue b/app/assets/javascripts/repository/components/upload_blob_modal.vue
new file mode 100644
index 00000000000..ec7ba469ca0
--- /dev/null
+++ b/app/assets/javascripts/repository/components/upload_blob_modal.vue
@@ -0,0 +1,220 @@
+<script>
+import {
+ GlModal,
+ GlForm,
+ GlFormGroup,
+ GlFormInput,
+ GlFormTextarea,
+ GlToggle,
+ GlButton,
+ GlAlert,
+} from '@gitlab/ui';
+import createFlash from '~/flash';
+import axios from '~/lib/utils/axios_utils';
+import { ContentTypeMultipartFormData } from '~/lib/utils/headers';
+import { numberToHumanSize } from '~/lib/utils/number_utils';
+import { visitUrl, joinPaths } from '~/lib/utils/url_utility';
+import { __ } from '~/locale';
+import { trackFileUploadEvent } from '~/projects/upload_file_experiment_tracking';
+import UploadDropzone from '~/vue_shared/components/upload_dropzone/upload_dropzone.vue';
+
+const PRIMARY_OPTIONS_TEXT = __('Upload file');
+const SECONDARY_OPTIONS_TEXT = __('Cancel');
+const MODAL_TITLE = __('Upload New File');
+const COMMIT_LABEL = __('Commit message');
+const TARGET_BRANCH_LABEL = __('Target branch');
+const TOGGLE_CREATE_MR_LABEL = __('Start a new merge request with these changes');
+const REMOVE_FILE_TEXT = __('Remove file');
+const NEW_BRANCH_IN_FORK = __(
+ 'A new branch will be created in your fork and a new merge request will be started.',
+);
+const ERROR_MESSAGE = __('Error uploading file. Please try again.');
+
+export default {
+ components: {
+ GlModal,
+ GlForm,
+ GlFormGroup,
+ GlFormInput,
+ GlFormTextarea,
+ GlToggle,
+ GlButton,
+ UploadDropzone,
+ GlAlert,
+ },
+ i18n: {
+ MODAL_TITLE,
+ COMMIT_LABEL,
+ TARGET_BRANCH_LABEL,
+ TOGGLE_CREATE_MR_LABEL,
+ REMOVE_FILE_TEXT,
+ NEW_BRANCH_IN_FORK,
+ },
+ props: {
+ modalId: {
+ type: String,
+ required: true,
+ },
+ commitMessage: {
+ type: String,
+ required: true,
+ },
+ targetBranch: {
+ type: String,
+ required: true,
+ },
+ originalBranch: {
+ type: String,
+ required: true,
+ },
+ canPushCode: {
+ type: Boolean,
+ required: true,
+ },
+ path: {
+ type: String,
+ required: true,
+ },
+ },
+ data() {
+ return {
+ commit: this.commitMessage,
+ target: this.targetBranch,
+ createNewMr: true,
+ file: null,
+ filePreviewURL: null,
+ fileBinary: null,
+ loading: false,
+ };
+ },
+ computed: {
+ primaryOptions() {
+ return {
+ text: PRIMARY_OPTIONS_TEXT,
+ attributes: [
+ {
+ variant: 'success',
+ loading: this.loading,
+ disabled: !this.formCompleted || this.loading,
+ },
+ ],
+ };
+ },
+ cancelOptions() {
+ return {
+ text: SECONDARY_OPTIONS_TEXT,
+ attributes: [
+ {
+ disabled: this.loading,
+ },
+ ],
+ };
+ },
+ formattedFileSize() {
+ return numberToHumanSize(this.file.size);
+ },
+ showCreateNewMrToggle() {
+ return this.canPushCode && this.target !== this.originalBranch;
+ },
+ formCompleted() {
+ return this.file && this.commit && this.target;
+ },
+ },
+ methods: {
+ setFile(file) {
+ this.file = file;
+
+ const fileUurlReader = new FileReader();
+
+ fileUurlReader.readAsDataURL(this.file);
+
+ fileUurlReader.onload = (e) => {
+ this.filePreviewURL = e.target?.result;
+ };
+ },
+ removeFile() {
+ this.file = null;
+ this.filePreviewURL = null;
+ },
+ uploadFile() {
+ this.loading = true;
+
+ const {
+ $route: {
+ params: { path },
+ },
+ } = 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);
+ });
+ },
+ },
+};
+</script>
+<template>
+ <gl-form>
+ <gl-modal
+ :modal-id="modalId"
+ :title="$options.i18n.MODAL_TITLE"
+ :action-primary="primaryOptions"
+ :action-cancel="cancelOptions"
+ @primary.prevent="uploadFile"
+ >
+ <upload-dropzone class="gl-h-200! gl-mb-4" single-file-selection @change="setFile">
+ <div
+ v-if="file"
+ class="card upload-dropzone-card upload-dropzone-border gl-w-full gl-h-full gl-align-items-center gl-justify-content-center gl-p-3"
+ >
+ <img v-if="filePreviewURL" :src="filePreviewURL" class="gl-h-11" />
+ <div>{{ formattedFileSize }}</div>
+ <div>{{ file.name }}</div>
+ <gl-button
+ category="tertiary"
+ variant="confirm"
+ :disabled="loading"
+ @click="removeFile"
+ >{{ $options.i18n.REMOVE_FILE_TEXT }}</gl-button
+ >
+ </div>
+ </upload-dropzone>
+ <gl-form-group :label="$options.i18n.COMMIT_LABEL" label-for="commit_message">
+ <gl-form-textarea v-model="commit" name="commit_message" :disabled="loading" />
+ </gl-form-group>
+ <gl-form-group
+ v-if="canPushCode"
+ :label="$options.i18n.TARGET_BRANCH_LABEL"
+ label-for="branch_name"
+ >
+ <gl-form-input v-model="target" :disabled="loading" name="branch_name" />
+ </gl-form-group>
+ <gl-toggle
+ v-if="showCreateNewMrToggle"
+ v-model="createNewMr"
+ :disabled="loading"
+ :label="$options.i18n.TOGGLE_CREATE_MR_LABEL"
+ />
+ <gl-alert v-if="!canPushCode" variant="info" :dismissible="false" class="gl-mt-3">
+ {{ $options.i18n.NEW_BRANCH_IN_FORK }}
+ </gl-alert>
+ </gl-modal>
+ </gl-form>
+</template>