diff options
author | Denys Mishunov <dmishunov@gitlab.com> | 2019-06-26 14:50:31 +0000 |
---|---|---|
committer | Phil Hughes <me@iamphill.com> | 2019-06-26 14:50:31 +0000 |
commit | f0fc53589755d00320b8c12ae739ba6c18872c3c (patch) | |
tree | 5fffcfa518cb76e34c3debbbcb19d275dcc9f4fc | |
parent | 4b7f053a49168491215e8ee20060c7283e138858 (diff) | |
download | gitlab-ce-f0fc53589755d00320b8c12ae739ba6c18872c3c.tar.gz |
Re-name entries in one commit
Update window's URL after entry's re-name
Set proper hook for correct fileLanguage
Filtered out `moved` entries from the tree
-rw-r--r-- | app/assets/javascripts/ide/components/ide_tree_list.vue | 7 | ||||
-rw-r--r-- | app/assets/javascripts/ide/stores/actions.js | 12 | ||||
-rw-r--r-- | app/assets/javascripts/ide/stores/actions/file.js | 4 | ||||
-rw-r--r-- | app/assets/javascripts/ide/stores/mutations.js | 9 | ||||
-rw-r--r-- | app/assets/javascripts/ide/stores/utils.js | 4 | ||||
-rw-r--r-- | app/assets/javascripts/ide/utils.js | 2 | ||||
-rw-r--r-- | changelogs/unreleased/58802-rename-webide.yml | 5 | ||||
-rw-r--r-- | spec/frontend/ide/utils_spec.js | 44 | ||||
-rw-r--r-- | spec/javascripts/ide/components/ide_tree_list_spec.js | 14 | ||||
-rw-r--r-- | spec/javascripts/ide/stores/actions/file_spec.js | 37 | ||||
-rw-r--r-- | spec/javascripts/ide/stores/actions_spec.js | 10 | ||||
-rw-r--r-- | spec/javascripts/ide/stores/mutations_spec.js | 11 |
12 files changed, 133 insertions, 26 deletions
diff --git a/app/assets/javascripts/ide/components/ide_tree_list.vue b/app/assets/javascripts/ide/components/ide_tree_list.vue index 95782b2c88a..1af86a94482 100644 --- a/app/assets/javascripts/ide/components/ide_tree_list.vue +++ b/app/assets/javascripts/ide/components/ide_tree_list.vue @@ -30,6 +30,9 @@ export default { showLoading() { return !this.currentTree || this.currentTree.loading; }, + actualTreeList() { + return this.currentTree.tree.filter(entry => !entry.moved); + }, }, mounted() { this.updateViewer(this.viewerType); @@ -54,9 +57,9 @@ export default { <slot name="header"></slot> </header> <div class="ide-tree-body h-100"> - <template v-if="currentTree.tree.length"> + <template v-if="actualTreeList.length"> <file-row - v-for="file in currentTree.tree" + v-for="file in actualTreeList" :key="file.key" :file="file" :level="0" diff --git a/app/assets/javascripts/ide/stores/actions.js b/app/assets/javascripts/ide/stores/actions.js index 48aabaf9dcf..507dc363529 100644 --- a/app/assets/javascripts/ide/stores/actions.js +++ b/app/assets/javascripts/ide/stores/actions.js @@ -8,6 +8,7 @@ import * as types from './mutation_types'; import { decorateFiles } from '../lib/files'; import { stageKeys } from '../constants'; import service from '../services'; +import router from '../ide_router'; export const redirectToUrl = (self, url) => visitUrl(url); @@ -234,10 +235,15 @@ export const renameEntry = ( parentPath: newParentPath, }); }); - } + } else { + const newPath = parentPath ? `${parentPath}/${name}` : name; + const newEntry = state.entries[newPath]; + commit(types.TOGGLE_FILE_CHANGED, { file: newEntry, changed: true }); - if (!entryPath && !entry.tempFile) { - dispatch('deleteEntry', path); + if (entry.opened) { + router.push(`/project${newEntry.url}`); + commit(types.TOGGLE_FILE_OPEN, entry.path); + } } dispatch('triggerFilesChange'); diff --git a/app/assets/javascripts/ide/stores/actions/file.js b/app/assets/javascripts/ide/stores/actions/file.js index dc40a1fa6a2..7627b6e03af 100644 --- a/app/assets/javascripts/ide/stores/actions/file.js +++ b/app/assets/javascripts/ide/stores/actions/file.js @@ -73,7 +73,9 @@ export const getFileData = ( .getFileData(joinPaths(gon.relative_url_root || '', url.replace('/-/', '/'))) .then(({ data, headers }) => { const normalizedHeaders = normalizeHeaders(headers); - setPageTitle(decodeURI(normalizedHeaders['PAGE-TITLE'])); + let title = normalizedHeaders['PAGE-TITLE']; + title = file.prevPath ? title.replace(file.prevPath, file.path) : title; + setPageTitle(decodeURI(title)); if (data) commit(types.SET_FILE_DATA, { data, file }); if (openFile) commit(types.TOGGLE_FILE_OPEN, path); diff --git a/app/assets/javascripts/ide/stores/mutations.js b/app/assets/javascripts/ide/stores/mutations.js index ae42b87c9a7..ec4c2fdcde2 100644 --- a/app/assets/javascripts/ide/stores/mutations.js +++ b/app/assets/javascripts/ide/stores/mutations.js @@ -216,15 +216,16 @@ export default { Vue.set(state.entries, newPath, { ...oldEntry, id: newPath, - key: `${newPath}-${oldEntry.type}-${oldEntry.id}`, + key: `${newPath}-${oldEntry.type}-${oldEntry.path}`, path: newPath, name: entryPath ? oldEntry.name : name, tempFile: true, prevPath: oldEntry.tempFile ? null : oldEntry.path, url: oldEntry.url.replace(new RegExp(`${oldEntry.path}/?$`), newPath), tree: [], - parentPath, raw: '', + opened: false, + parentPath, }); oldEntry.moved = true; @@ -241,10 +242,6 @@ export default { state.changedFiles = state.changedFiles.concat(newEntry); } - if (state.entries[newPath].opened) { - state.openFiles.push(state.entries[newPath]); - } - if (oldEntry.tempFile) { const filterMethod = f => f.path !== oldEntry.path; diff --git a/app/assets/javascripts/ide/stores/utils.js b/app/assets/javascripts/ide/stores/utils.js index 4e7a8765abe..fb132c1afc1 100644 --- a/app/assets/javascripts/ide/stores/utils.js +++ b/app/assets/javascripts/ide/stores/utils.js @@ -147,9 +147,9 @@ export const createCommitPayload = ({ commit_message: state.commitMessage || getters.preBuiltCommitMessage, actions: getCommitFiles(rootState.stagedFiles).map(f => ({ action: commitActionForFile(f), - file_path: f.path, + file_path: f.moved ? f.movedPath : f.path, previous_path: f.prevPath === '' ? undefined : f.prevPath, - content: f.content || undefined, + content: f.prevPath ? null : f.content || undefined, encoding: f.base64 ? 'base64' : 'text', last_commit_id: newBranch || f.deleted || f.prevPath ? undefined : f.lastCommitSha, })), diff --git a/app/assets/javascripts/ide/utils.js b/app/assets/javascripts/ide/utils.js index d895eca7af0..ae579fef25f 100644 --- a/app/assets/javascripts/ide/utils.js +++ b/app/assets/javascripts/ide/utils.js @@ -3,7 +3,7 @@ import { commitItemIconMap } from './constants'; export const getCommitIconMap = file => { if (file.deleted) { return commitItemIconMap.deleted; - } else if (file.tempFile) { + } else if (file.tempFile && !file.prevPath) { return commitItemIconMap.addition; } diff --git a/changelogs/unreleased/58802-rename-webide.yml b/changelogs/unreleased/58802-rename-webide.yml new file mode 100644 index 00000000000..40471d967ce --- /dev/null +++ b/changelogs/unreleased/58802-rename-webide.yml @@ -0,0 +1,5 @@ +--- +title: Re-name files in Web IDE in a more natural way +merge_request: 29948 +author: +type: changed diff --git a/spec/frontend/ide/utils_spec.js b/spec/frontend/ide/utils_spec.js new file mode 100644 index 00000000000..2b7dffdcd88 --- /dev/null +++ b/spec/frontend/ide/utils_spec.js @@ -0,0 +1,44 @@ +import { commitItemIconMap } from '~/ide/constants'; +import { getCommitIconMap } from '~/ide/utils'; +import { decorateData } from '~/ide/stores/utils'; + +describe('WebIDE utils', () => { + const createFile = (name = 'name', id = name, type = '', parent = null) => + decorateData({ + id, + type, + icon: 'icon', + url: 'url', + name, + path: parent ? `${parent.path}/${name}` : name, + parentPath: parent ? parent.path : '', + lastCommit: {}, + }); + + describe('getCommitIconMap', () => { + let entry; + + beforeEach(() => { + entry = createFile('Entry item'); + }); + + it('renders "deleted" icon for deleted entries', () => { + entry.deleted = true; + expect(getCommitIconMap(entry)).toEqual(commitItemIconMap.deleted); + }); + it('renders "addition" icon for temp entries', () => { + entry.tempFile = true; + expect(getCommitIconMap(entry)).toEqual(commitItemIconMap.addition); + }); + it('renders "modified" icon for newly-renamed entries', () => { + entry.prevPath = 'foo/bar'; + entry.tempFile = false; + expect(getCommitIconMap(entry)).toEqual(commitItemIconMap.modified); + }); + it('renders "modified" icon even for temp entries if they are newly-renamed', () => { + entry.prevPath = 'foo/bar'; + entry.tempFile = true; + expect(getCommitIconMap(entry)).toEqual(commitItemIconMap.modified); + }); + }); +}); diff --git a/spec/javascripts/ide/components/ide_tree_list_spec.js b/spec/javascripts/ide/components/ide_tree_list_spec.js index f63007c7dd2..554bd1ae3b5 100644 --- a/spec/javascripts/ide/components/ide_tree_list_spec.js +++ b/spec/javascripts/ide/components/ide_tree_list_spec.js @@ -58,6 +58,20 @@ describe('IDE tree list', () => { it('renders list of files', () => { expect(vm.$el.textContent).toContain('fileName'); }); + + it('does not render moved entries', done => { + const tree = [file('moved entry'), file('normal entry')]; + tree[0].moved = true; + store.state.trees['abcproject/master'].tree = tree; + const container = vm.$el.querySelector('.ide-tree-body'); + + vm.$nextTick(() => { + expect(container.children.length).toBe(1); + expect(vm.$el.textContent).not.toContain('moved entry'); + expect(vm.$el.textContent).toContain('normal entry'); + done(); + }); + }); }); describe('empty-branch state', () => { diff --git a/spec/javascripts/ide/stores/actions/file_spec.js b/spec/javascripts/ide/stores/actions/file_spec.js index dd2313dc800..021c3076094 100644 --- a/spec/javascripts/ide/stores/actions/file_spec.js +++ b/spec/javascripts/ide/stores/actions/file_spec.js @@ -275,6 +275,43 @@ describe('IDE store file actions', () => { }); }); + describe('Re-named success', () => { + beforeEach(() => { + localFile = file(`newCreate-${Math.random()}`); + localFile.url = `project/getFileDataURL`; + localFile.prevPath = 'old-dull-file'; + localFile.path = 'new-shiny-file'; + store.state.entries[localFile.path] = localFile; + + mock.onGet(`${RELATIVE_URL_ROOT}/project/getFileDataURL`).replyOnce( + 200, + { + blame_path: 'blame_path', + commits_path: 'commits_path', + permalink: 'permalink', + raw_path: 'raw_path', + binary: false, + html: '123', + render_error: '', + }, + { + 'page-title': 'testing old-dull-file', + }, + ); + }); + + it('sets document title considering `prevPath` on a file', done => { + store + .dispatch('getFileData', { path: localFile.path }) + .then(() => { + expect(document.title).toBe('testing new-shiny-file'); + + done(); + }) + .catch(done.fail); + }); + }); + describe('error', () => { beforeEach(() => { mock.onGet(`project/getFileDataURL`).networkError(); diff --git a/spec/javascripts/ide/stores/actions_spec.js b/spec/javascripts/ide/stores/actions_spec.js index 537152f5eed..2d105103c1c 100644 --- a/spec/javascripts/ide/stores/actions_spec.js +++ b/spec/javascripts/ide/stores/actions_spec.js @@ -536,8 +536,15 @@ describe('Multi-file store actions', () => { type: types.RENAME_ENTRY, payload: { path: 'test', name: 'new-name', entryPath: null, parentPath: 'parent-path' }, }, + { + type: types.TOGGLE_FILE_CHANGED, + payload: { + file: store.state.entries['parent-path/new-name'], + changed: true, + }, + }, ], - [{ type: 'deleteEntry', payload: 'test' }, { type: 'triggerFilesChange' }], + [{ type: 'triggerFilesChange' }], done, ); }); @@ -584,7 +591,6 @@ describe('Multi-file store actions', () => { parentPath: 'parent-path/new-name', }, }, - { type: 'deleteEntry', payload: 'test' }, { type: 'triggerFilesChange' }, ], done, diff --git a/spec/javascripts/ide/stores/mutations_spec.js b/spec/javascripts/ide/stores/mutations_spec.js index 5ee098bf17f..460c5b01081 100644 --- a/spec/javascripts/ide/stores/mutations_spec.js +++ b/spec/javascripts/ide/stores/mutations_spec.js @@ -309,7 +309,7 @@ describe('Multi-file store mutations', () => { ...localState.entries.oldPath, id: 'newPath', name: 'newPath', - key: 'newPath-blob-name', + key: 'newPath-blob-oldPath', path: 'newPath', tempFile: true, prevPath: 'oldPath', @@ -318,6 +318,7 @@ describe('Multi-file store mutations', () => { url: `${gl.TEST_HOST}/newPath`, moved: jasmine.anything(), movedPath: jasmine.anything(), + opened: false, }); }); @@ -349,13 +350,5 @@ describe('Multi-file store mutations', () => { expect(localState.entries.parentPath.tree.length).toBe(1); }); - - it('adds to openFiles if previously opened', () => { - localState.entries.oldPath.opened = true; - - mutations.RENAME_ENTRY(localState, { path: 'oldPath', name: 'newPath' }); - - expect(localState.openFiles).toEqual([localState.entries.newPath]); - }); }); }); |