gitlab-org--gitlab-foss/app/assets/javascripts/ide/components/new_dropdown/modal.vue

189 lines
5.0 KiB
Vue

<script>
import { GlModal, GlButton } from '@gitlab/ui';
import { mapActions, mapState, mapGetters } from 'vuex';
import createFlash from '~/flash';
import { __, sprintf } from '~/locale';
import { modalTypes } from '../../constants';
import { trimPathComponents, getPathParent } from '../../utils';
const i18n = {
cancelButtonText: __('Cancel'),
};
export default {
components: {
GlModal,
GlButton,
},
data() {
return {
entryName: '',
modalType: modalTypes.blob,
path: '',
};
},
computed: {
...mapState(['entries']),
...mapGetters('fileTemplates', ['templateTypes']),
modalTitle() {
const entry = this.entries[this.path];
if (this.modalType === modalTypes.tree) {
return __('Create new directory');
} else if (this.modalType === modalTypes.rename) {
return entry.type === modalTypes.tree ? __('Rename folder') : __('Rename file');
}
return __('Create new file');
},
buttonLabel() {
const entry = this.entries[this.path];
if (this.modalType === modalTypes.tree) {
return __('Create directory');
} else if (this.modalType === modalTypes.rename) {
return entry.type === modalTypes.tree ? __('Rename folder') : __('Rename file');
}
return __('Create file');
},
actionPrimary() {
return {
text: this.buttonLabel,
attributes: [{ variant: 'confirm' }],
};
},
actionCancel() {
return {
text: i18n.cancelButtonText,
attributes: [{ variant: 'default' }],
};
},
isCreatingNewFile() {
return this.modalType === modalTypes.blob;
},
placeholder() {
return this.isCreatingNewFile ? 'dir/file_name' : 'dir/';
},
},
methods: {
...mapActions(['createTempEntry', 'renameEntry']),
submitForm() {
this.entryName = trimPathComponents(this.entryName);
if (this.modalType === modalTypes.rename) {
if (this.entries[this.entryName] && !this.entries[this.entryName].deleted) {
createFlash({
message: sprintf(__('The name "%{name}" is already taken in this directory.'), {
name: this.entryName,
}),
fadeTransition: false,
addBodyClass: true,
});
} else {
let parentPath = this.entryName.split('/');
const name = parentPath.pop();
parentPath = parentPath.join('/');
this.renameEntry({
path: this.path,
name,
parentPath,
});
}
} else {
this.createTempEntry({
name: this.entryName,
type: this.modalType,
});
}
},
createFromTemplate(template) {
const parent = getPathParent(this.entryName);
const name = parent ? `${parent}/${template.name}` : template.name;
this.createTempEntry({
name,
type: this.modalType,
});
this.$refs.modal.toggle();
},
focusInput() {
const name = this.entries[this.entryName]?.name;
const inputValue = this.$refs.fieldName.value;
this.$refs.fieldName.focus();
if (name) {
this.$refs.fieldName.setSelectionRange(inputValue.indexOf(name), inputValue.length);
}
},
resetData() {
this.entryName = '';
this.path = '';
this.modalType = modalTypes.blob;
},
open(type = modalTypes.blob, path = '') {
this.modalType = type;
this.path = path;
if (this.modalType === modalTypes.rename) {
this.entryName = path;
} else {
this.entryName = path ? `${path}/` : '';
}
this.$refs.modal.show();
// wait for modal to show first
this.$nextTick(() => this.focusInput());
},
close() {
this.$refs.modal.hide();
},
},
};
</script>
<template>
<gl-modal
ref="modal"
modal-id="ide-new-entry"
data-qa-selector="new_file_modal"
data-testid="ide-new-entry"
:title="modalTitle"
size="lg"
:action-primary="actionPrimary"
:action-cancel="actionCancel"
@primary="submitForm"
@cancel="resetData"
>
<div class="form-group row">
<label class="label-bold col-form-label col-sm-2"> {{ __('Name') }} </label>
<div class="col-sm-10">
<input
ref="fieldName"
v-model.trim="entryName"
type="text"
class="form-control"
data-testid="file-name-field"
data-qa-selector="file_name_field"
:placeholder="placeholder"
/>
<ul v-if="isCreatingNewFile" class="file-templates gl-mt-3 list-inline qa-template-list">
<li v-for="(template, index) in templateTypes" :key="index" class="list-inline-item">
<gl-button
variant="dashed"
category="secondary"
class="p-1 pr-2 pl-2"
@click="createFromTemplate(template)"
>
{{ template.name }}
</gl-button>
</li>
</ul>
</div>
</div>
</gl-modal>
</template>