diff options
19 files changed, 93 insertions, 74 deletions
diff --git a/app/assets/javascripts/repo/components/new_dropdown/index.vue b/app/assets/javascripts/repo/components/new_dropdown/index.vue index 53baa02c344..5e93ce7bc0f 100644 --- a/app/assets/javascripts/repo/components/new_dropdown/index.vue +++ b/app/assets/javascripts/repo/components/new_dropdown/index.vue @@ -1,4 +1,5 @@ <script> + import { mapState } from 'vuex'; import newModal from './modal.vue'; export default { @@ -11,6 +12,11 @@ modalType: '', }; }, + computed: { + ...mapState([ + 'path', + ]), + }, methods: { createNewItem(type) { this.modalType = type; @@ -64,6 +70,7 @@ <new-modal v-if="openModal" :type="modalType" + :path="path" @toggle="toggleModalOpen" /> </div> diff --git a/app/assets/javascripts/repo/components/new_dropdown/modal.vue b/app/assets/javascripts/repo/components/new_dropdown/modal.vue index bb22dc4caa9..e780b88b04c 100644 --- a/app/assets/javascripts/repo/components/new_dropdown/modal.vue +++ b/app/assets/javascripts/repo/components/new_dropdown/modal.vue @@ -9,10 +9,14 @@ type: String, required: true, }, + path: { + type: String, + required: true, + }, }, data() { return { - entryName: '', + entryName: this.path !== '' ? `${this.path}/` : '', }; }, components: { @@ -24,7 +28,7 @@ ]), createEntryInStore() { this.createTempEntry({ - name: this.entryName, + name: this.entryName.replace(new RegExp(`^${this.path}\/`), ''), type: this.type, }); @@ -35,17 +39,6 @@ }, }, computed: { - ...mapState([ - 'path', - ]), - name: { - get() { - return this.path !== '' ? `${this.path}/${this.entryName}` : this.entryName; - }, - set(newVal) { - this.entryName = newVal.replace(`${this.path}/`, ''); - }, - }, modalTitle() { if (this.type === 'tree') { return __('Create new directory'); @@ -95,7 +88,7 @@ <input type="text" class="form-control" - v-model="name" + v-model="entryName" ref="fieldName" /> </div> diff --git a/app/assets/javascripts/repo/components/repo.vue b/app/assets/javascripts/repo/components/repo.vue index 31a88b297c0..1f0e168c777 100644 --- a/app/assets/javascripts/repo/components/repo.vue +++ b/app/assets/javascripts/repo/components/repo.vue @@ -13,7 +13,7 @@ export default { 'currentBlobView', ]), ...mapGetters([ - 'isMini', + 'isCollapsed', 'changedFiles', ]), }, @@ -26,15 +26,12 @@ export default { RepoPreview, }, mounted() { + const alertMessage = 'Are you sure you want to lose unsaved changes?'; window.onbeforeunload = (e) => { - const event = e || window.event; - if (!this.changedFiles.length) return undefined; - if (event) event.returnValue = 'Are you sure you want to lose unsaved changes?'; - - // For Safari - return 'Are you sure you want to lose unsaved changes?'; + e.returnValue = alertMessage; + return alertMessage; }; }, }; @@ -42,10 +39,10 @@ export default { <template> <div class="repository-view"> - <div class="tree-content-holder" :class="{'tree-content-holder-mini' : isMini}"> + <div class="tree-content-holder" :class="{'tree-content-holder-mini' : isCollapsed}"> <repo-sidebar/> <div - v-if="isMini" + v-if="isCollapsed" class="panel-right" > <repo-tabs/> diff --git a/app/assets/javascripts/repo/components/repo_commit_section.vue b/app/assets/javascripts/repo/components/repo_commit_section.vue index 37fc35f35c9..fb613e8af9d 100644 --- a/app/assets/javascripts/repo/components/repo_commit_section.vue +++ b/app/assets/javascripts/repo/components/repo_commit_section.vue @@ -33,6 +33,7 @@ export default { ...mapActions([ 'checkCommitStatus', 'commitChanges', + 'getTreeData', ]), makeCommit(newBranch = false) { const createNewBranch = newBranch || this.startNewMR; @@ -54,6 +55,7 @@ export default { this.commitChanges({ payload, newMr: this.startNewMR }) .then(() => { this.submitCommitsLoading = false; + this.getTreeData(); }) .catch(() => { this.submitCommitsLoading = false; diff --git a/app/assets/javascripts/repo/components/repo_editor.vue b/app/assets/javascripts/repo/components/repo_editor.vue index 6e9669403f2..0d6729bb99b 100644 --- a/app/assets/javascripts/repo/components/repo_editor.vue +++ b/app/assets/javascripts/repo/components/repo_editor.vue @@ -92,5 +92,10 @@ export default { </script> <template> - <div id="ide" v-if='!shouldHideEditor' class="blob-viewer-container blob-editor-container"></div> + <div + id="ide" + v-if='!shouldHideEditor' + class="blob-viewer-container blob-editor-container" + > + </div> </template> diff --git a/app/assets/javascripts/repo/components/repo_file.vue b/app/assets/javascripts/repo/components/repo_file.vue index 77895174f15..7a23154b340 100644 --- a/app/assets/javascripts/repo/components/repo_file.vue +++ b/app/assets/javascripts/repo/components/repo_file.vue @@ -14,7 +14,7 @@ }, computed: { ...mapGetters([ - 'isMini', + 'isCollapsed', ]), fileIcon() { return { @@ -71,7 +71,7 @@ </template> </td> - <template v-if="!isMini"> + <template v-if="!isCollapsed"> <td class="hidden-sm hidden-xs"> <a @click.stop diff --git a/app/assets/javascripts/repo/components/repo_loading_file.vue b/app/assets/javascripts/repo/components/repo_loading_file.vue index 51a2aade464..1e6c405f292 100644 --- a/app/assets/javascripts/repo/components/repo_loading_file.vue +++ b/app/assets/javascripts/repo/components/repo_loading_file.vue @@ -4,7 +4,7 @@ export default { computed: { ...mapGetters([ - 'isMini', + 'isCollapsed', ]), }, methods: { @@ -30,7 +30,7 @@ </div> </div> </td> - <template v-if="!isMini"> + <template v-if="!isCollapsed"> <td class="hidden-sm hidden-xs"> <div class="animation-container"> diff --git a/app/assets/javascripts/repo/components/repo_prev_directory.vue b/app/assets/javascripts/repo/components/repo_prev_directory.vue index 3c623dd8020..a2b305bbd05 100644 --- a/app/assets/javascripts/repo/components/repo_prev_directory.vue +++ b/app/assets/javascripts/repo/components/repo_prev_directory.vue @@ -7,10 +7,10 @@ 'parentTreeUrl', ]), ...mapGetters([ - 'isMini', + 'isCollapsed', ]), colSpanCondition() { - return this.isMini ? undefined : 3; + return this.isCollapsed ? undefined : 3; }, }, methods: { diff --git a/app/assets/javascripts/repo/components/repo_preview.vue b/app/assets/javascripts/repo/components/repo_preview.vue index bbe5c667254..b189a603c57 100644 --- a/app/assets/javascripts/repo/components/repo_preview.vue +++ b/app/assets/javascripts/repo/components/repo_preview.vue @@ -7,6 +7,9 @@ export default { ...mapGetters([ 'activeFile', ]), + renderErrorTooLarge() { + return this.activeFile.renderError == 'too_large'; + }, }, methods: { highlightFile() { @@ -35,7 +38,7 @@ export default { v-html="activeFile.html"> </div> <div - v-else-if="activeFile.renderError == 'too_large'" + v-else-if="renderErrorTooLarge" class="vertical-center render-error"> <p class="text-center"> The source could not be displayed because it is too large. You can <a :href="activeFile.rawPath" download>download</a> it instead. diff --git a/app/assets/javascripts/repo/components/repo_sidebar.vue b/app/assets/javascripts/repo/components/repo_sidebar.vue index 34eaa26cf72..63c0d70f5c0 100644 --- a/app/assets/javascripts/repo/components/repo_sidebar.vue +++ b/app/assets/javascripts/repo/components/repo_sidebar.vue @@ -31,7 +31,7 @@ export default { }), ...mapGetters([ 'treeList', - 'isMini', + 'isCollapsed', ]), }, methods: { @@ -44,12 +44,12 @@ export default { </script> <template> -<div id="sidebar" :class="{'sidebar-mini' : isMini}"> +<div id="sidebar" :class="{'sidebar-mini' : isCollapsed}"> <table class="table"> <thead> <tr> <th - v-if="isMini" + v-if="isCollapsed" class="repo-file-options title" > <strong class="clgray"> diff --git a/app/assets/javascripts/repo/stores/actions.js b/app/assets/javascripts/repo/stores/actions.js index d5dc57e331b..008de3d8315 100644 --- a/app/assets/javascripts/repo/stores/actions.js +++ b/app/assets/javascripts/repo/stores/actions.js @@ -2,6 +2,9 @@ import Vue from 'vue'; import flash from '../../flash'; import service from '../services'; import * as types from './mutation_types'; +import { + pushState, +} from './utils'; export const redirectToUrl = url => gl.utils.visitUrl(url); @@ -67,6 +70,7 @@ export const checkCommitStatus = ({ state }) => service.getBranchData( export const commitChanges = ({ commit, state, dispatch }, { payload, newMr }) => service.commit(state.project.id, payload) .then((data) => { + const { branch } = payload; if (!data.short_id) { flash(data.message); return; @@ -75,9 +79,8 @@ export const commitChanges = ({ commit, state, dispatch }, { payload, newMr }) = flash(`Your changes have been committed. Commit ${data.short_id} with ${data.stats.additions} additions, ${data.stats.deletions} deletions.`, 'notice'); if (newMr) { - redirectToUrl(`${state.endpoints.newMergeRequestUrl}${payload.branch}`); + redirectToUrl(`${state.endpoints.newMergeRequestUrl}${branch}`); } else { - // TODO: push a new state with the branch name commit(types.SET_COMMIT_REF, data.id); dispatch('discardAllChanges'); dispatch('closeAllFiles'); diff --git a/app/assets/javascripts/repo/stores/getters.js b/app/assets/javascripts/repo/stores/getters.js index 9122578cc79..1ed05ac6e35 100644 --- a/app/assets/javascripts/repo/stores/getters.js +++ b/app/assets/javascripts/repo/stores/getters.js @@ -1,5 +1,10 @@ import _ from 'underscore'; +/* + Takes the multi-dimensional tree and returns a flattened array. + This allows for the table to recursively render the table rows but keeps the data + structure nested to make it easier to add new files/directories. +*/ export const treeList = (state) => { const mapTree = arr => (!arr.tree.length ? [] : _.map(arr.tree, a => [a, mapTree(a)])); @@ -9,11 +14,7 @@ export const treeList = (state) => { .value(); }; -export const changedFiles = (state) => { - const files = state.openFiles; - - return files.filter(file => file.changed); -}; +export const changedFiles = state => state.openFiles.filter(file => file.changed); export const activeFile = state => state.openFiles.find(file => file.active); @@ -22,7 +23,7 @@ export const activeFileExtension = (state) => { return file ? `.${file.path.split('.').pop()}` : ''; }; -export const isMini = state => !!state.openFiles.length; +export const isCollapsed = state => !!state.openFiles.length; export const canEditFile = (state) => { const currentActiveFile = activeFile(state); diff --git a/app/assets/javascripts/repo/stores/state.js b/app/assets/javascripts/repo/stores/state.js index 1301350c627..aab74754f02 100644 --- a/app/assets/javascripts/repo/stores/state.js +++ b/app/assets/javascripts/repo/stores/state.js @@ -1,23 +1,23 @@ export default () => ({ - project: { - id: 0, - name: '', - url: '', - }, - endpoints: {}, - isRoot: false, - isInitialRoot: false, + canCommit: false, currentBranch: '', + currentBlobView: 'repo-preview', currentRef: '', - path: '', - canCommit: false, - onTopOfBranch: false, + discardPopupOpen: false, editMode: false, + endpoints: {}, + isRoot: false, + isInitialRoot: false, loading: false, - currentBlobView: 'repo-preview', - discardPopupOpen: false, - tree: [], + onTopOfBranch: false, openFiles: [], + path: '', + project: { + id: 0, + name: '', + url: '', + }, parentTreeUrl: '', previousUrl: '', + tree: [], }); diff --git a/app/views/projects/tree/_tree_header.html.haml b/app/views/projects/tree/_tree_header.html.haml index 40266047bad..c02f7ee37ed 100644 --- a/app/views/projects/tree/_tree_header.html.haml +++ b/app/views/projects/tree/_tree_header.html.haml @@ -2,7 +2,7 @@ .tree-ref-holder = render 'shared/ref_switcher', destination: 'tree', path: @path, show_create: true - - if show_new_repo? + - if show_new_repo? && can_push_branch?(@project, @ref) .js-new-dropdown - else = render 'projects/tree/old_tree_header' diff --git a/spec/features/projects/tree/create_file_spec.rb b/spec/features/projects/tree/create_file_spec.rb index a67ec891e7c..f75122abad3 100644 --- a/spec/features/projects/tree/create_file_spec.rb +++ b/spec/features/projects/tree/create_file_spec.rb @@ -28,7 +28,7 @@ feature 'Multi-file editor new file', :js do click_button('Create file') end - find('.inputarea').send_keys('file content') + find('.inputarea', visible: false).send_keys('file content') fill_in('commit-message', with: 'commit message') diff --git a/spec/javascripts/repo/components/repo_edit_button_spec.js b/spec/javascripts/repo/components/repo_edit_button_spec.js index aee2dd6ad55..44018464b35 100644 --- a/spec/javascripts/repo/components/repo_edit_button_spec.js +++ b/spec/javascripts/repo/components/repo_edit_button_spec.js @@ -15,7 +15,6 @@ describe('RepoEditButton', () => { }); f.active = true; - f.changed = true; vm.$store.dispatch('setInitialData', { canCommit: true, onTopOfBranch: true, @@ -45,17 +44,23 @@ describe('RepoEditButton', () => { expect(vm.$el.querySelector('.btn').textContent.trim()).toBe('Cancel edit'); }); - it('toggles edit mode on click', () => { + it('toggles edit mode on click', (done) => { vm.$mount(); vm.$el.querySelector('.btn').click(); - expect(vm.$el.querySelector('.btn').textContent.trim()).toBe('Cancel edit'); + vm.$nextTick(() => { + expect(vm.$el.querySelector('.btn').textContent.trim()).toBe('Cancel edit'); + + done(); + }); }); describe('discardPopupOpen', () => { beforeEach(() => { vm.$store.state.discardPopupOpen = true; + vm.$store.state.editMode = true; + vm.$store.state.openFiles[0].changed = true; vm.$mount(); }); diff --git a/spec/javascripts/repo/components/repo_file_spec.js b/spec/javascripts/repo/components/repo_file_spec.js index 18ae461128e..c45f8a18d1f 100644 --- a/spec/javascripts/repo/components/repo_file_spec.js +++ b/spec/javascripts/repo/components/repo_file_spec.js @@ -5,6 +5,7 @@ import { file, resetStore } from '../helpers'; describe('RepoFile', () => { const updated = 'updated'; + let vm; function createComponent(propsData) { const RepoFile = Vue.extend(repoFile); @@ -21,7 +22,7 @@ describe('RepoFile', () => { it('renders link, icon, name and last commit details', () => { const RepoFile = Vue.extend(repoFile); - const vm = new RepoFile({ + vm = new RepoFile({ store, propsData: { file: file(), @@ -43,7 +44,7 @@ describe('RepoFile', () => { }); it('does render if hasFiles is true and is loading tree', () => { - const vm = createComponent({ + vm = createComponent({ file: file(), }); @@ -53,7 +54,7 @@ describe('RepoFile', () => { it('renders a spinner if the file is loading', () => { const f = file(); f.loading = true; - const vm = createComponent({ + vm = createComponent({ file: f, }); @@ -62,7 +63,7 @@ describe('RepoFile', () => { }); it('does not render commit message and datetime if mini', (done) => { - const vm = createComponent({ + vm = createComponent({ file: file(), }); vm.$store.state.openFiles.push(vm.file); @@ -76,7 +77,7 @@ describe('RepoFile', () => { }); it('fires clickedTreeRow when the link is clicked', () => { - const vm = createComponent({ + vm = createComponent({ file: file(), }); @@ -89,7 +90,6 @@ describe('RepoFile', () => { describe('submodule', () => { let f; - let vm; beforeEach(() => { f = file('submodule name', '123456789'); diff --git a/spec/javascripts/repo/components/repo_tab_spec.js b/spec/javascripts/repo/components/repo_tab_spec.js index 0d1c22a2f89..df0ca55aafc 100644 --- a/spec/javascripts/repo/components/repo_tab_spec.js +++ b/spec/javascripts/repo/components/repo_tab_spec.js @@ -4,6 +4,8 @@ import repoTab from '~/repo/components/repo_tab.vue'; import { file, resetStore } from '../helpers'; describe('RepoTab', () => { + let vm; + function createComponent(propsData) { const RepoTab = Vue.extend(repoTab); @@ -18,7 +20,7 @@ describe('RepoTab', () => { }); it('renders a close link and a name link', () => { - const vm = createComponent({ + vm = createComponent({ tab: file(), }); vm.$store.state.openFiles.push(vm.tab); @@ -30,7 +32,7 @@ describe('RepoTab', () => { }); it('calls setFileActive when clicking tab', () => { - const vm = createComponent({ + vm = createComponent({ tab: file(), }); @@ -42,7 +44,7 @@ describe('RepoTab', () => { }); it('calls closeFile when clicking close button', () => { - const vm = createComponent({ + vm = createComponent({ tab: file(), }); @@ -56,7 +58,7 @@ describe('RepoTab', () => { it('renders an fa-circle icon if tab is changed', () => { const tab = file(); tab.changed = true; - const vm = createComponent({ + vm = createComponent({ tab, }); @@ -69,7 +71,7 @@ describe('RepoTab', () => { const tab = file(); tab.changed = true; tab.opened = true; - const vm = createComponent({ + vm = createComponent({ tab, }); vm.$store.state.openFiles.push(tab); @@ -87,7 +89,7 @@ describe('RepoTab', () => { it('closes tab when clicking close btn', (done) => { const tab = file('lose'); tab.opened = true; - const vm = createComponent({ + vm = createComponent({ tab, }); vm.$store.state.openFiles.push(tab); diff --git a/spec/javascripts/repo/components/repo_tabs_spec.js b/spec/javascripts/repo/components/repo_tabs_spec.js index 73ecdab6967..d0246cc72e6 100644 --- a/spec/javascripts/repo/components/repo_tabs_spec.js +++ b/spec/javascripts/repo/components/repo_tabs_spec.js @@ -5,6 +5,7 @@ import { file, resetStore } from '../helpers'; describe('RepoTabs', () => { const openedFiles = [file(), file()]; + let vm; function createComponent() { const RepoTabs = Vue.extend(repoTabs); @@ -19,7 +20,7 @@ describe('RepoTabs', () => { }); it('renders a list of tabs', (done) => { - const vm = createComponent(); + vm = createComponent(); openedFiles[0].active = true; vm.$store.state.openFiles = openedFiles; |