parent
5295f23b4b
commit
caee9d5882
12 changed files with 257 additions and 32 deletions
|
@ -0,0 +1,70 @@
|
||||||
|
<script>
|
||||||
|
import newModal from './modal.vue';
|
||||||
|
|
||||||
|
export default {
|
||||||
|
components: {
|
||||||
|
newModal,
|
||||||
|
},
|
||||||
|
data() {
|
||||||
|
return {
|
||||||
|
openModal: false,
|
||||||
|
modalType: '',
|
||||||
|
};
|
||||||
|
},
|
||||||
|
methods: {
|
||||||
|
createNewItem(type) {
|
||||||
|
this.modalType = type;
|
||||||
|
this.toggleModalOpen();
|
||||||
|
},
|
||||||
|
toggleModalOpen() {
|
||||||
|
this.openModal = !this.openModal;
|
||||||
|
},
|
||||||
|
},
|
||||||
|
};
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<template>
|
||||||
|
<div class="breadcrumb repo-breadcrumb">
|
||||||
|
<div class="dropdown">
|
||||||
|
<button
|
||||||
|
type="button"
|
||||||
|
class="btn btn-default dropdown-toggle add-to-tree"
|
||||||
|
data-toggle="dropdown"
|
||||||
|
data-target=".add-to-tree-dropdown"
|
||||||
|
>
|
||||||
|
<i
|
||||||
|
class="fa fa-plus"
|
||||||
|
aria-hidden="true"
|
||||||
|
>
|
||||||
|
</i>
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
<div class="add-to-tree-dropdown">
|
||||||
|
<ul class="dropdown-menu">
|
||||||
|
<li>
|
||||||
|
<a
|
||||||
|
href="#"
|
||||||
|
role="button"
|
||||||
|
@click.prevent="createNewItem('blob')"
|
||||||
|
>
|
||||||
|
{{ __('New file') }}
|
||||||
|
</a>
|
||||||
|
</li>
|
||||||
|
<li>
|
||||||
|
<a
|
||||||
|
href="#"
|
||||||
|
role="button"
|
||||||
|
@click.prevent="createNewItem('tree')"
|
||||||
|
>
|
||||||
|
{{ __('New directory') }}
|
||||||
|
</a>
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
|
</div>
|
||||||
|
<new-modal
|
||||||
|
v-if="openModal"
|
||||||
|
:type="modalType"
|
||||||
|
@toggle="toggleModalOpen"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
</template>
|
115
app/assets/javascripts/repo/components/new_dropdown/modal.vue
Normal file
115
app/assets/javascripts/repo/components/new_dropdown/modal.vue
Normal file
|
@ -0,0 +1,115 @@
|
||||||
|
<script>
|
||||||
|
import { __ } from '../../../locale';
|
||||||
|
import popupDialog from '../../../vue_shared/components/popup_dialog.vue';
|
||||||
|
import RepoStore from '../../stores/repo_store';
|
||||||
|
import RepoHelper from '../../helpers/repo_helper';
|
||||||
|
|
||||||
|
export default {
|
||||||
|
props: {
|
||||||
|
type: {
|
||||||
|
type: String,
|
||||||
|
required: true,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
data() {
|
||||||
|
return {
|
||||||
|
entryName: '',
|
||||||
|
};
|
||||||
|
},
|
||||||
|
components: {
|
||||||
|
popupDialog,
|
||||||
|
},
|
||||||
|
methods: {
|
||||||
|
createEntryInStore() {
|
||||||
|
if (this.entryName === '') return;
|
||||||
|
|
||||||
|
const fileName = this.type === 'tree' ? '.gitkeep' : this.entryName;
|
||||||
|
let tree = null;
|
||||||
|
|
||||||
|
if (this.type === 'tree') {
|
||||||
|
tree = RepoHelper.serializeTree({
|
||||||
|
name: this.entryName,
|
||||||
|
path: this.entryName,
|
||||||
|
tempFile: true,
|
||||||
|
});
|
||||||
|
RepoStore.files.push(tree);
|
||||||
|
|
||||||
|
RepoHelper.setDirectoryOpen(tree, tree.name);
|
||||||
|
}
|
||||||
|
|
||||||
|
const file = RepoHelper.serializeBlob({
|
||||||
|
name: fileName,
|
||||||
|
path: tree ? `${tree}/${fileName}` : fileName,
|
||||||
|
tempFile: true,
|
||||||
|
});
|
||||||
|
|
||||||
|
if (tree) {
|
||||||
|
RepoStore.addFilesToDirectory(tree, RepoStore.files, [file]);
|
||||||
|
} else {
|
||||||
|
RepoStore.addFilesToDirectory(tree, RepoStore.files, [...RepoStore.files, file]);
|
||||||
|
}
|
||||||
|
|
||||||
|
RepoHelper.setFile(file, file);
|
||||||
|
RepoStore.editMode = true;
|
||||||
|
RepoStore.toggleBlobView();
|
||||||
|
|
||||||
|
this.toggleModalOpen();
|
||||||
|
},
|
||||||
|
toggleModalOpen() {
|
||||||
|
this.$emit('toggle');
|
||||||
|
},
|
||||||
|
},
|
||||||
|
computed: {
|
||||||
|
modalTitle() {
|
||||||
|
if (this.type === 'tree') {
|
||||||
|
return __('Create new directory');
|
||||||
|
}
|
||||||
|
|
||||||
|
return __('Create new file');
|
||||||
|
},
|
||||||
|
buttonLabel() {
|
||||||
|
if (this.type === 'tree') {
|
||||||
|
return __('Create directory');
|
||||||
|
}
|
||||||
|
|
||||||
|
return __('Create file');
|
||||||
|
},
|
||||||
|
formLabelName() {
|
||||||
|
if (this.type === 'tree') {
|
||||||
|
return __('Directory name');
|
||||||
|
}
|
||||||
|
|
||||||
|
return __('File name');
|
||||||
|
},
|
||||||
|
},
|
||||||
|
};
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<template>
|
||||||
|
<popup-dialog
|
||||||
|
:title="modalTitle"
|
||||||
|
:primary-button-label="buttonLabel"
|
||||||
|
kind="success"
|
||||||
|
@toggle="toggleModalOpen"
|
||||||
|
@submit="createEntryInStore"
|
||||||
|
>
|
||||||
|
<form
|
||||||
|
class="form-horizontal"
|
||||||
|
slot="body"
|
||||||
|
@submit.prevent="createEntryInStore"
|
||||||
|
>
|
||||||
|
<fieldset class="form-group append-bottom-0">
|
||||||
|
<label class="label-light col-sm-3">
|
||||||
|
{{ formLabelName }}
|
||||||
|
</label>
|
||||||
|
<div class="col-sm-9">
|
||||||
|
<input
|
||||||
|
type="text"
|
||||||
|
class="form-control"
|
||||||
|
v-model="entryName"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
</fieldset>
|
||||||
|
</form>
|
||||||
|
</popup-dialog>
|
||||||
|
</template>
|
|
@ -49,7 +49,7 @@ export default {
|
||||||
// see https://docs.gitlab.com/ce/api/commits.html#create-a-commit-with-multiple-files-and-actions
|
// see https://docs.gitlab.com/ce/api/commits.html#create-a-commit-with-multiple-files-and-actions
|
||||||
const commitMessage = this.commitMessage;
|
const commitMessage = this.commitMessage;
|
||||||
const actions = this.changedFiles.map(f => ({
|
const actions = this.changedFiles.map(f => ({
|
||||||
action: 'update',
|
action: f.tempFile ? 'create' : 'update',
|
||||||
file_path: f.path,
|
file_path: f.path,
|
||||||
content: f.newContent,
|
content: f.newContent,
|
||||||
}));
|
}));
|
||||||
|
|
|
@ -16,11 +16,22 @@ const RepoEditor = {
|
||||||
},
|
},
|
||||||
|
|
||||||
mounted() {
|
mounted() {
|
||||||
|
if (!this.activeFile.tempFile) {
|
||||||
Service.getRaw(this.activeFile.raw_path)
|
Service.getRaw(this.activeFile.raw_path)
|
||||||
.then((rawResponse) => {
|
.then((rawResponse) => {
|
||||||
Store.blobRaw = rawResponse.data;
|
Store.blobRaw = rawResponse.data;
|
||||||
Store.activeFile.plain = rawResponse.data;
|
Store.activeFile.plain = rawResponse.data;
|
||||||
|
|
||||||
|
this.createMonacoInstance();
|
||||||
|
})
|
||||||
|
.catch(Helper.loadingError);
|
||||||
|
} else {
|
||||||
|
this.createMonacoInstance();
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
methods: {
|
||||||
|
createMonacoInstance() {
|
||||||
const monacoInstance = Helper.monaco.editor.create(this.$el, {
|
const monacoInstance = Helper.monaco.editor.create(this.$el, {
|
||||||
model: null,
|
model: null,
|
||||||
readOnly: false,
|
readOnly: false,
|
||||||
|
@ -33,11 +44,7 @@ const RepoEditor = {
|
||||||
this.addMonacoEvents();
|
this.addMonacoEvents();
|
||||||
|
|
||||||
this.setupEditor();
|
this.setupEditor();
|
||||||
})
|
|
||||||
.catch(Helper.loadingError);
|
|
||||||
},
|
},
|
||||||
|
|
||||||
methods: {
|
|
||||||
setupEditor() {
|
setupEditor() {
|
||||||
this.showHide();
|
this.showHide();
|
||||||
|
|
||||||
|
|
|
@ -11,7 +11,12 @@ const RepoFileButtons = {
|
||||||
mixins: [RepoMixin],
|
mixins: [RepoMixin],
|
||||||
|
|
||||||
computed: {
|
computed: {
|
||||||
|
showButtons() {
|
||||||
|
return this.activeFile.raw_path ||
|
||||||
|
this.activeFile.blame_path ||
|
||||||
|
this.activeFile.commits_path ||
|
||||||
|
this.activeFile.permalink;
|
||||||
|
},
|
||||||
rawDownloadButtonLabel() {
|
rawDownloadButtonLabel() {
|
||||||
return this.binary ? 'Download' : 'Raw';
|
return this.binary ? 'Download' : 'Raw';
|
||||||
},
|
},
|
||||||
|
@ -30,7 +35,10 @@ export default RepoFileButtons;
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
<div id="repo-file-buttons">
|
<div
|
||||||
|
v-if="showButtons"
|
||||||
|
id="repo-file-buttons"
|
||||||
|
>
|
||||||
<a
|
<a
|
||||||
:href="activeFile.raw_path"
|
:href="activeFile.raw_path"
|
||||||
target="_blank"
|
target="_blank"
|
||||||
|
|
|
@ -18,8 +18,8 @@ const RepoTab = {
|
||||||
},
|
},
|
||||||
changedClass() {
|
changedClass() {
|
||||||
const tabChangedObj = {
|
const tabChangedObj = {
|
||||||
'fa-times close-icon': !this.tab.changed,
|
'fa-times close-icon': !this.tab.changed && !this.tab.tempFile,
|
||||||
'fa-circle unsaved-icon': this.tab.changed,
|
'fa-circle unsaved-icon': this.tab.changed || this.tab.tempFile,
|
||||||
};
|
};
|
||||||
return tabChangedObj;
|
return tabChangedObj;
|
||||||
},
|
},
|
||||||
|
|
|
@ -157,7 +157,7 @@ const RepoHelper = {
|
||||||
},
|
},
|
||||||
|
|
||||||
serializeRepoEntity(type, entity, level = 0) {
|
serializeRepoEntity(type, entity, level = 0) {
|
||||||
const { id, url, name, icon, last_commit, tree_url } = entity;
|
const { id, url, name, icon, last_commit, tree_url, path, tempFile } = entity;
|
||||||
|
|
||||||
return {
|
return {
|
||||||
id,
|
id,
|
||||||
|
@ -165,7 +165,9 @@ const RepoHelper = {
|
||||||
name,
|
name,
|
||||||
url,
|
url,
|
||||||
tree_url,
|
tree_url,
|
||||||
|
path,
|
||||||
level,
|
level,
|
||||||
|
tempFile,
|
||||||
icon: `fa-${icon}`,
|
icon: `fa-${icon}`,
|
||||||
files: [],
|
files: [],
|
||||||
loading: false,
|
loading: false,
|
||||||
|
|
|
@ -5,6 +5,7 @@ import Service from './services/repo_service';
|
||||||
import Store from './stores/repo_store';
|
import Store from './stores/repo_store';
|
||||||
import Repo from './components/repo.vue';
|
import Repo from './components/repo.vue';
|
||||||
import RepoEditButton from './components/repo_edit_button.vue';
|
import RepoEditButton from './components/repo_edit_button.vue';
|
||||||
|
import newDropdown from './components/new_dropdown/index.vue';
|
||||||
import Translate from '../vue_shared/translate';
|
import Translate from '../vue_shared/translate';
|
||||||
|
|
||||||
function initDropdowns() {
|
function initDropdowns() {
|
||||||
|
@ -62,9 +63,22 @@ function initRepoEditButton(el) {
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function initNewDropdown(el) {
|
||||||
|
return new Vue({
|
||||||
|
el,
|
||||||
|
components: {
|
||||||
|
newDropdown,
|
||||||
|
},
|
||||||
|
render(createElement) {
|
||||||
|
return createElement('new-dropdown');
|
||||||
|
},
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
function initRepoBundle() {
|
function initRepoBundle() {
|
||||||
const repo = document.getElementById('repo');
|
const repo = document.getElementById('repo');
|
||||||
const editButton = document.querySelector('.editable-mode');
|
const editButton = document.querySelector('.editable-mode');
|
||||||
|
const newDropdownHolder = document.querySelector('.js-new-dropdown');
|
||||||
setInitialStore(repo.dataset);
|
setInitialStore(repo.dataset);
|
||||||
addEventsForNonVueEls();
|
addEventsForNonVueEls();
|
||||||
initDropdowns();
|
initDropdowns();
|
||||||
|
@ -73,6 +87,7 @@ function initRepoBundle() {
|
||||||
|
|
||||||
initRepo(repo);
|
initRepo(repo);
|
||||||
initRepoEditButton(editButton);
|
initRepoEditButton(editButton);
|
||||||
|
initNewDropdown(newDropdownHolder);
|
||||||
}
|
}
|
||||||
|
|
||||||
$(initRepoBundle);
|
$(initRepoBundle);
|
||||||
|
|
|
@ -8,7 +8,7 @@ const RepoMixin = {
|
||||||
|
|
||||||
changedFiles() {
|
changedFiles() {
|
||||||
const changedFileList = this.openedFiles
|
const changedFileList = this.openedFiles
|
||||||
.filter(file => file.changed);
|
.filter(file => file.changed || file.tempFile);
|
||||||
return changedFileList;
|
return changedFileList;
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
|
|
@ -75,7 +75,7 @@ const RepoStore = {
|
||||||
RepoStore.blobRaw = file.base64;
|
RepoStore.blobRaw = file.base64;
|
||||||
} else if (file.newContent || file.plain) {
|
} else if (file.newContent || file.plain) {
|
||||||
RepoStore.blobRaw = file.newContent || file.plain;
|
RepoStore.blobRaw = file.newContent || file.plain;
|
||||||
} else {
|
} else if (!file.tempFile) {
|
||||||
Service.getRaw(file.raw_path)
|
Service.getRaw(file.raw_path)
|
||||||
.then((rawResponse) => {
|
.then((rawResponse) => {
|
||||||
RepoStore.blobRaw = rawResponse.data;
|
RepoStore.blobRaw = rawResponse.data;
|
||||||
|
@ -120,6 +120,11 @@ const RepoStore = {
|
||||||
return openedFile.path !== file.path;
|
return openedFile.path !== file.path;
|
||||||
});
|
});
|
||||||
|
|
||||||
|
// remove the file from the sidebar if it is a tempFile
|
||||||
|
if (file.tempFile) {
|
||||||
|
RepoStore.files = RepoStore.files.filter(f => !(f.tempFile && f.path === file.path));
|
||||||
|
}
|
||||||
|
|
||||||
// now activate the right tab based on what you closed.
|
// now activate the right tab based on what you closed.
|
||||||
if (RepoStore.openedFiles.length === 0) {
|
if (RepoStore.openedFiles.length === 0) {
|
||||||
RepoStore.activeFile = {};
|
RepoStore.activeFile = {};
|
||||||
|
|
|
@ -9,7 +9,7 @@ export default {
|
||||||
},
|
},
|
||||||
text: {
|
text: {
|
||||||
type: String,
|
type: String,
|
||||||
required: true,
|
required: false,
|
||||||
},
|
},
|
||||||
kind: {
|
kind: {
|
||||||
type: String,
|
type: String,
|
||||||
|
@ -82,10 +82,11 @@ export default {
|
||||||
type="button"
|
type="button"
|
||||||
class="btn"
|
class="btn"
|
||||||
:class="btnCancelKindClass"
|
:class="btnCancelKindClass"
|
||||||
@click="emitSubmit(false)">
|
@click="close">
|
||||||
{{ closeButtonLabel }}
|
{{ closeButtonLabel }}
|
||||||
</button>
|
</button>
|
||||||
<button type="button"
|
<button
|
||||||
|
type="button"
|
||||||
class="btn"
|
class="btn"
|
||||||
:class="btnKindClass"
|
:class="btnKindClass"
|
||||||
@click="emitSubmit(true)">
|
@click="emitSubmit(true)">
|
||||||
|
|
|
@ -2,7 +2,9 @@
|
||||||
.tree-ref-holder
|
.tree-ref-holder
|
||||||
= render 'shared/ref_switcher', destination: 'tree', path: @path
|
= render 'shared/ref_switcher', destination: 'tree', path: @path
|
||||||
|
|
||||||
- unless show_new_repo?
|
- if show_new_repo?
|
||||||
|
.js-new-dropdown
|
||||||
|
- else
|
||||||
= render 'projects/tree/old_tree_header'
|
= render 'projects/tree/old_tree_header'
|
||||||
|
|
||||||
.tree-controls
|
.tree-controls
|
||||||
|
|
Loading…
Reference in a new issue