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/snippets/components/snippet_blob_actions_edit.vue')
-rw-r--r--app/assets/javascripts/snippets/components/snippet_blob_actions_edit.vue156
1 files changed, 156 insertions, 0 deletions
diff --git a/app/assets/javascripts/snippets/components/snippet_blob_actions_edit.vue b/app/assets/javascripts/snippets/components/snippet_blob_actions_edit.vue
new file mode 100644
index 00000000000..55cd13a6930
--- /dev/null
+++ b/app/assets/javascripts/snippets/components/snippet_blob_actions_edit.vue
@@ -0,0 +1,156 @@
+<script>
+import { GlButton } from '@gitlab/ui';
+import { cloneDeep } from 'lodash';
+import { s__, sprintf } from '~/locale';
+import glFeatureFlagsMixin from '~/vue_shared/mixins/gl_feature_flags_mixin';
+import SnippetBlobEdit from './snippet_blob_edit.vue';
+import { SNIPPET_MAX_BLOBS } from '../constants';
+import { createBlob, decorateBlob, diffAll } from '../utils/blob';
+
+export default {
+ components: {
+ SnippetBlobEdit,
+ GlButton,
+ },
+ mixins: [glFeatureFlagsMixin()],
+ props: {
+ initBlobs: {
+ type: Array,
+ required: true,
+ },
+ },
+ data() {
+ return {
+ // This is a dictionary (by .id) of the original blobs and
+ // is used as the baseline for calculating diffs
+ // (e.g., what has been deleted, changed, renamed, etc.)
+ blobsOrig: {},
+ // This is a dictionary (by .id) of the current blobs and
+ // is updated as the user makes changes.
+ blobs: {},
+ // This is a list of blob ID's in order how they should be
+ // presented.
+ blobIds: [],
+ };
+ },
+ computed: {
+ actions() {
+ return diffAll(this.blobs, this.blobsOrig);
+ },
+ count() {
+ return this.blobIds.length;
+ },
+ addLabel() {
+ return sprintf(s__('Snippets|Add another file %{num}/%{total}'), {
+ num: this.count,
+ total: SNIPPET_MAX_BLOBS,
+ });
+ },
+ canDelete() {
+ return this.count > 1;
+ },
+ canAdd() {
+ return this.count < SNIPPET_MAX_BLOBS;
+ },
+ hasMultiFilesEnabled() {
+ return this.glFeatures.snippetMultipleFiles;
+ },
+ filesLabel() {
+ return this.hasMultiFilesEnabled ? s__('Snippets|Files') : s__('Snippets|File');
+ },
+ firstInputId() {
+ const blobId = this.blobIds[0];
+
+ if (!blobId) {
+ return '';
+ }
+
+ return `${blobId}_file_path`;
+ },
+ },
+ watch: {
+ actions: {
+ immediate: true,
+ handler(val) {
+ this.$emit('actions', val);
+ },
+ },
+ },
+ created() {
+ const blobs = this.initBlobs.map(decorateBlob);
+ const blobsById = blobs.reduce((acc, x) => Object.assign(acc, { [x.id]: x }), {});
+
+ this.blobsOrig = blobsById;
+ this.blobs = cloneDeep(blobsById);
+ this.blobIds = blobs.map(x => x.id);
+
+ // Show 1 empty blob if none exist
+ if (!this.blobIds.length) {
+ this.addBlob();
+ }
+ },
+ methods: {
+ updateBlobContent(id, content) {
+ const origBlob = this.blobsOrig[id];
+ const blob = this.blobs[id];
+
+ blob.content = content;
+
+ // If we've received content, but we haven't loaded the content before
+ // then this is also the original content.
+ if (origBlob && !origBlob.isLoaded) {
+ blob.isLoaded = true;
+ origBlob.isLoaded = true;
+ origBlob.content = content;
+ }
+ },
+ updateBlobFilePath(id, path) {
+ const blob = this.blobs[id];
+
+ blob.path = path;
+ },
+ addBlob() {
+ const blob = createBlob();
+
+ this.$set(this.blobs, blob.id, blob);
+ this.blobIds.push(blob.id);
+ },
+ deleteBlob(id) {
+ this.blobIds = this.blobIds.filter(x => x !== id);
+ this.$delete(this.blobs, id);
+ },
+ updateBlob(id, args) {
+ if ('content' in args) {
+ this.updateBlobContent(id, args.content);
+ }
+ if ('path' in args) {
+ this.updateBlobFilePath(id, args.path);
+ }
+ },
+ },
+};
+</script>
+<template>
+ <div class="form-group file-editor">
+ <label :for="firstInputId">{{ filesLabel }}</label>
+ <snippet-blob-edit
+ v-for="(blobId, index) in blobIds"
+ :key="blobId"
+ :class="{ 'gl-mt-3': index > 0 }"
+ :blob="blobs[blobId]"
+ :can-delete="canDelete"
+ :show-delete="hasMultiFilesEnabled"
+ @blob-updated="updateBlob(blobId, $event)"
+ @delete="deleteBlob(blobId)"
+ />
+ <gl-button
+ v-if="hasMultiFilesEnabled"
+ :disabled="!canAdd"
+ data-testid="add_button"
+ class="gl-my-3"
+ variant="dashed"
+ @click="addBlob"
+ >{{ addLabel }}</gl-button
+ >
+ </div>
+</template>