188 lines
5 KiB
Vue
188 lines
5 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>
|