diff options
Diffstat (limited to 'app/assets/javascripts/vue_shared/components/rich_content_editor/modals/add_image')
2 files changed, 203 insertions, 0 deletions
diff --git a/app/assets/javascripts/vue_shared/components/rich_content_editor/modals/add_image/add_image_modal.vue b/app/assets/javascripts/vue_shared/components/rich_content_editor/modals/add_image/add_image_modal.vue new file mode 100644 index 00000000000..0a444b2295d --- /dev/null +++ b/app/assets/javascripts/vue_shared/components/rich_content_editor/modals/add_image/add_image_modal.vue @@ -0,0 +1,147 @@ +<script> +import { isSafeURL } from '~/lib/utils/url_utility'; +import { GlModal, GlFormGroup, GlFormInput, GlTabs, GlTab } from '@gitlab/ui'; +import { __ } from '~/locale'; +import glFeatureFlagMixin from '~/vue_shared/mixins/gl_feature_flags_mixin'; +import { IMAGE_TABS } from '../../constants'; +import UploadImageTab from './upload_image_tab.vue'; + +export default { + components: { + UploadImageTab, + GlModal, + GlFormGroup, + GlFormInput, + GlTabs, + GlTab, + }, + mixins: [glFeatureFlagMixin()], + props: { + imageRoot: { + type: String, + required: true, + }, + }, + data() { + return { + file: null, + urlError: null, + imageUrl: null, + description: null, + tabIndex: IMAGE_TABS.UPLOAD_TAB, + uploadImageTab: null, + }; + }, + modalTitle: __('Image Details'), + okTitle: __('Insert'), + urlTabTitle: __('By URL'), + urlLabel: __('Image URL'), + descriptionLabel: __('Description'), + uploadTabTitle: __('Upload file'), + computed: { + altText() { + return this.description; + }, + }, + methods: { + show() { + this.file = null; + this.urlError = null; + this.imageUrl = null; + this.description = null; + this.tabIndex = IMAGE_TABS.UPLOAD_TAB; + + this.$refs.modal.show(); + }, + onOk(event) { + if (this.glFeatures.sseImageUploads && this.tabIndex === IMAGE_TABS.UPLOAD_TAB) { + this.submitFile(event); + return; + } + this.submitURL(event); + }, + setFile(file) { + this.file = file; + }, + submitFile(event) { + const { file, altText } = this; + const { uploadImageTab } = this.$refs; + + uploadImageTab.validateFile(); + + if (uploadImageTab.fileError) { + event.preventDefault(); + return; + } + + const imageUrl = `${this.imageRoot}${file.name}`; + + this.$emit('addImage', { imageUrl, file, altText: altText || file.name }); + }, + submitURL(event) { + if (!this.validateUrl()) { + event.preventDefault(); + return; + } + + const { imageUrl, altText } = this; + + this.$emit('addImage', { imageUrl, altText: altText || imageUrl }); + }, + validateUrl() { + if (!isSafeURL(this.imageUrl)) { + this.urlError = __('Please provide a valid URL'); + this.$refs.urlInput.$el.focus(); + return false; + } + + return true; + }, + }, +}; +</script> +<template> + <gl-modal + ref="modal" + modal-id="add-image-modal" + :title="$options.modalTitle" + :ok-title="$options.okTitle" + @ok="onOk" + > + <gl-tabs v-if="glFeatures.sseImageUploads" v-model="tabIndex"> + <!-- Upload file Tab --> + <gl-tab :title="$options.uploadTabTitle"> + <upload-image-tab ref="uploadImageTab" @input="setFile" /> + </gl-tab> + + <!-- By URL Tab --> + <gl-tab :title="$options.urlTabTitle"> + <gl-form-group + class="gl-mt-5 gl-mb-3" + :label="$options.urlLabel" + label-for="url-input" + :state="!Boolean(urlError)" + :invalid-feedback="urlError" + > + <gl-form-input id="url-input" ref="urlInput" v-model="imageUrl" /> + </gl-form-group> + </gl-tab> + </gl-tabs> + + <gl-form-group + v-else + class="gl-mt-5 gl-mb-3" + :label="$options.urlLabel" + label-for="url-input" + :state="!Boolean(urlError)" + :invalid-feedback="urlError" + > + <gl-form-input id="url-input" ref="urlInput" v-model="imageUrl" /> + </gl-form-group> + + <!-- Description Input --> + <gl-form-group :label="$options.descriptionLabel" label-for="description-input"> + <gl-form-input id="description-input" ref="descriptionInput" v-model="description" /> + </gl-form-group> + </gl-modal> +</template> diff --git a/app/assets/javascripts/vue_shared/components/rich_content_editor/modals/add_image/upload_image_tab.vue b/app/assets/javascripts/vue_shared/components/rich_content_editor/modals/add_image/upload_image_tab.vue new file mode 100644 index 00000000000..739f8b502c9 --- /dev/null +++ b/app/assets/javascripts/vue_shared/components/rich_content_editor/modals/add_image/upload_image_tab.vue @@ -0,0 +1,56 @@ +<script> +import { __ } from '~/locale'; +import { GlFormGroup } from '@gitlab/ui'; +import { MAX_FILE_SIZE } from '../../constants'; + +export default { + components: { + GlFormGroup, + }, + data() { + return { + file: null, + fileError: null, + }; + }, + fileLabel: __('Select file'), + methods: { + onInput(event) { + [this.file] = event.target.files; + + this.validateFile(); + + if (!this.fileError) { + this.$emit('input', this.file); + } + }, + validateFile() { + this.fileError = null; + + if (!this.file) { + this.fileError = __('Please choose a file'); + } else if (this.file.size > MAX_FILE_SIZE) { + this.fileError = __('Maximum file size is 2MB. Please select a smaller file.'); + } + }, + }, +}; +</script> +<template> + <gl-form-group + class="gl-mt-5 gl-mb-3" + :label="$options.fileLabel" + label-for="file-input" + :state="!Boolean(fileError)" + :invalid-feedback="fileError" + > + <input + id="file-input" + ref="fileInput" + class="gl-mt-3 gl-mb-2" + type="file" + accept="image/*" + @input="onInput" + /> + </gl-form-group> +</template> |