diff options
author | Tim Zallmann <tzallmann@gitlab.com> | 2018-06-04 11:44:39 +0200 |
---|---|---|
committer | Tim Zallmann <tzallmann@gitlab.com> | 2018-06-08 11:49:01 +0200 |
commit | 4d8d4ff28f918c21f427c8592006bb4ba7cff033 (patch) | |
tree | d22910c73ee7a5549ca273dc6f1a7fa497166c2a | |
parent | d6b1f1353e451ef4e26e68ff519e7d9a7317f534 (diff) | |
download | gitlab-ce-4d8d4ff28f918c21f427c8592006bb4ba7cff033.tar.gz |
Rewritten Even Handling for Swipe Viewer
13 files changed, 248 insertions, 243 deletions
diff --git a/app/assets/javascripts/ide/components/repo_editor.vue b/app/assets/javascripts/ide/components/repo_editor.vue index 83a22f25074..59a831bcc36 100644 --- a/app/assets/javascripts/ide/components/repo_editor.vue +++ b/app/assets/javascripts/ide/components/repo_editor.vue @@ -12,7 +12,6 @@ export default { components: {
ContentViewer,
DiffViewer,
- IdeFileButtons,
ExternalLink,
},
props: {
diff --git a/app/assets/javascripts/ide/ide_router.js b/app/assets/javascripts/ide/ide_router.js index 353994f79ad..b52618f4fde 100644 --- a/app/assets/javascripts/ide/ide_router.js +++ b/app/assets/javascripts/ide/ide_router.js @@ -1,181 +1,180 @@ -import Vue from 'vue';
-import VueRouter from 'vue-router';
-import flash from '~/flash';
-import store from './stores';
-import { activityBarViews } from './constants';
-
-Vue.use(VueRouter);
-
-/**
- * Routes below /-/ide/:
-
-/project/h5bp/html5-boilerplate/blob/master
-/project/h5bp/html5-boilerplate/blob/master/app/js/test.js
-
-/project/h5bp/html5-boilerplate/mr/123
-/project/h5bp/html5-boilerplate/mr/123/app/js/test.js
-
-/workspace/123
-/workspace/project/h5bp/html5-boilerplate/blob/my-special-branch
-/workspace/project/h5bp/html5-boilerplate/mr/123
-
-/ = /workspace
-
-/settings
-*/
-
-// Unfortunately Vue Router doesn't work without at least a fake component
-// If you do only data handling
-const EmptyRouterComponent = {
- render(createElement) {
- return createElement('div');
- },
-};
-
-const router = new VueRouter({
- mode: 'history',
- base: `${gon.relative_url_root}/-/ide/`,
- routes: [
- {
- path: '/project/:namespace/:project+',
- component: EmptyRouterComponent,
- children: [
- {
- path: ':targetmode(edit|tree|blob)/*',
- component: EmptyRouterComponent,
- },
- {
- path: 'merge_requests/:mrid',
- component: EmptyRouterComponent,
- },
- ],
- },
- ],
-});
-
-router.beforeEach((to, from, next) => {
- if (to.params.namespace && to.params.project) {
- store
- .dispatch('getProjectData', {
- namespace: to.params.namespace,
- projectId: to.params.project,
- })
- .then(() => {
- const fullProjectId = `${to.params.namespace}/${to.params.project}`;
-
- const baseSplit = (to.params[0] && to.params[0].split('/-/')) || [''];
- const branchId = baseSplit[0].slice(-1) === '/' ? baseSplit[0].slice(0, -1) : baseSplit[0];
-
- if (branchId) {
- const basePath = baseSplit.length > 1 ? baseSplit[1] : '';
-
- store.dispatch('setCurrentBranchId', branchId);
-
- store.dispatch('getBranchData', {
- projectId: fullProjectId,
- branchId,
- });
-
- store
- .dispatch('getFiles', {
- projectId: fullProjectId,
- branchId,
- })
- .then(() => {
- if (basePath) {
- const path = basePath.slice(-1) === '/' ? basePath.slice(0, -1) : basePath;
- const treeEntryKey = Object.keys(store.state.entries).find(
- key => key === path && !store.state.entries[key].pending,
- );
- const treeEntry = store.state.entries[treeEntryKey];
-
- if (treeEntry) {
- store.dispatch('handleTreeEntryAction', treeEntry);
- }
- }
- })
- .catch(e => {
- flash(
- 'Error while loading the branch files. Please try again.',
- 'alert',
- document,
- null,
- false,
- true,
- );
- throw e;
- });
- }
- } else if (to.params.mrid) {
- store
- .dispatch('getMergeRequestData', {
- projectId: fullProjectId,
- mergeRequestId: to.params.mrid,
- })
- .then(mr => {
- store.dispatch('updateActivityBarView', activityBarViews.review);
-
- store.dispatch('getBranchData', {
- projectId: fullProjectId,
- branchId: mr.source_branch,
- });
-
- return store.dispatch('getFiles', {
- projectId: fullProjectId,
- branchId: mr.source_branch,
- });
- })
- .then(() =>
- store.dispatch('getMergeRequestVersions', {
- projectId: fullProjectId,
- mergeRequestId: to.params.mrid,
- }),
- )
- .then(() =>
- store.dispatch('getMergeRequestChanges', {
- projectId: fullProjectId,
- mergeRequestId: to.params.mrid,
- }),
- )
- .then(mrChanges => {
- mrChanges.changes.forEach((change, ind) => {
- const changeTreeEntry = store.state.entries[change.new_path];
-
- if (changeTreeEntry) {
- store.dispatch('setFileMrChange', {
- file: changeTreeEntry,
- mrChange: change,
- });
-
- if (ind < 10) {
- store.dispatch('getFileData', {
- path: change.new_path,
- makeFileActive: ind === 0,
- });
- }
- }
- });
- })
- .catch(e => {
- flash('Error while loading the merge request. Please try again.');
- throw e;
- });
- }
- })
- .catch(e => {
- flash(
- 'Error while loading the project data. Please try again.',
- 'alert',
- document,
- null,
- false,
- true,
- );
- throw e;
- });
- }
-
- next();
-});
-
-export default router;
+import Vue from 'vue'; +import VueRouter from 'vue-router'; +import flash from '~/flash'; +import store from './stores'; +import { activityBarViews } from './constants'; + +Vue.use(VueRouter); + +/** + * Routes below /-/ide/: + +/project/h5bp/html5-boilerplate/blob/master +/project/h5bp/html5-boilerplate/blob/master/app/js/test.js + +/project/h5bp/html5-boilerplate/mr/123 +/project/h5bp/html5-boilerplate/mr/123/app/js/test.js + +/workspace/123 +/workspace/project/h5bp/html5-boilerplate/blob/my-special-branch +/workspace/project/h5bp/html5-boilerplate/mr/123 + +/ = /workspace + +/settings +*/ + +// Unfortunately Vue Router doesn't work without at least a fake component +// If you do only data handling +const EmptyRouterComponent = { + render(createElement) { + return createElement('div'); + }, +}; + +const router = new VueRouter({ + mode: 'history', + base: `${gon.relative_url_root}/-/ide/`, + routes: [ + { + path: '/project/:namespace/:project+', + component: EmptyRouterComponent, + children: [ + { + path: ':targetmode(edit|tree|blob)/*', + component: EmptyRouterComponent, + }, + { + path: 'merge_requests/:mrid', + component: EmptyRouterComponent, + }, + ], + }, + ], +}); + +router.beforeEach((to, from, next) => { + if (to.params.namespace && to.params.project) { + store + .dispatch('getProjectData', { + namespace: to.params.namespace, + projectId: to.params.project, + }) + .then(() => { + const fullProjectId = `${to.params.namespace}/${to.params.project}`; + + const baseSplit = (to.params[0] && to.params[0].split('/-/')) || ['']; + const branchId = baseSplit[0].slice(-1) === '/' ? baseSplit[0].slice(0, -1) : baseSplit[0]; + + if (branchId) { + const basePath = baseSplit.length > 1 ? baseSplit[1] : ''; + + store.dispatch('setCurrentBranchId', branchId); + + store.dispatch('getBranchData', { + projectId: fullProjectId, + branchId, + }); + + store + .dispatch('getFiles', { + projectId: fullProjectId, + branchId, + }) + .then(() => { + if (basePath) { + const path = basePath.slice(-1) === '/' ? basePath.slice(0, -1) : basePath; + const treeEntryKey = Object.keys(store.state.entries).find( + key => key === path && !store.state.entries[key].pending, + ); + const treeEntry = store.state.entries[treeEntryKey]; + + if (treeEntry) { + store.dispatch('handleTreeEntryAction', treeEntry); + } + } + }) + .catch(e => { + flash( + 'Error while loading the branch files. Please try again.', + 'alert', + document, + null, + false, + true, + ); + throw e; + }); + } else if (to.params.mrid) { + store + .dispatch('getMergeRequestData', { + projectId: fullProjectId, + mergeRequestId: to.params.mrid, + }) + .then(mr => { + store.dispatch('updateActivityBarView', activityBarViews.review); + + store.dispatch('getBranchData', { + projectId: fullProjectId, + branchId: mr.source_branch, + }); + + return store.dispatch('getFiles', { + projectId: fullProjectId, + branchId: mr.source_branch, + }); + }) + .then(() => + store.dispatch('getMergeRequestVersions', { + projectId: fullProjectId, + mergeRequestId: to.params.mrid, + }), + ) + .then(() => + store.dispatch('getMergeRequestChanges', { + projectId: fullProjectId, + mergeRequestId: to.params.mrid, + }), + ) + .then(mrChanges => { + mrChanges.changes.forEach((change, ind) => { + const changeTreeEntry = store.state.entries[change.new_path]; + + if (changeTreeEntry) { + store.dispatch('setFileMrChange', { + file: changeTreeEntry, + mrChange: change, + }); + + if (ind < 10) { + store.dispatch('getFileData', { + path: change.new_path, + makeFileActive: ind === 0, + }); + } + } + }); + }) + .catch(e => { + flash('Error while loading the merge request. Please try again.'); + throw e; + }); + } + }) + .catch(e => { + flash( + 'Error while loading the project data. Please try again.', + 'alert', + document, + null, + false, + true, + ); + throw e; + }); + } + + next(); +}); + +export default router; diff --git a/app/assets/javascripts/ide/stores/mutations/file.js b/app/assets/javascripts/ide/stores/mutations/file.js index f698aea4c43..5826f6cb828 100644 --- a/app/assets/javascripts/ide/stores/mutations/file.js +++ b/app/assets/javascripts/ide/stores/mutations/file.js @@ -94,11 +94,11 @@ export default { } else if (mrChange.renamed_file) { diffMode = diffModes.renamed; } - Object.assign(mrChange, { - diffMode, - }); Object.assign(state.entries[file.path], { - mrChange, + mrChange: { + ...mrChange, + diffMode, + }, }); }, [types.SET_FILE_VIEWMODE](state, { file, viewMode }) { diff --git a/app/assets/javascripts/vue_shared/components/content_viewer/viewers/download_viewer.vue b/app/assets/javascripts/vue_shared/components/content_viewer/viewers/download_viewer.vue index b21679aa0f4..c274d3ab590 100644 --- a/app/assets/javascripts/vue_shared/components/content_viewer/viewers/download_viewer.vue +++ b/app/assets/javascripts/vue_shared/components/content_viewer/viewers/download_viewer.vue @@ -33,7 +33,7 @@ export default { <div class="file-content"> <p class="prepend-top-10 file-info"> {{ fileName }} - <template v-if="fileSize>0"> + <template v-if="fileSize > 0"> ({{ fileSizeReadable }}) </template> </p> diff --git a/app/assets/javascripts/vue_shared/components/content_viewer/viewers/image_viewer.vue b/app/assets/javascripts/vue_shared/components/content_viewer/viewers/image_viewer.vue index aba6ecd3a75..439e749aaf6 100644 --- a/app/assets/javascripts/vue_shared/components/content_viewer/viewers/image_viewer.vue +++ b/app/assets/javascripts/vue_shared/components/content_viewer/viewers/image_viewer.vue @@ -66,7 +66,7 @@ export default { <div class="file-content image_file"> <img ref="contentImg" - :class="{ 'isZoomable': isZoomable, 'isZoomed': isZoomed }" + :class="{ 'is-zoomable': isZoomable, 'is-zoomed': isZoomed }" :src="path" :alt="path" @load="onImgLoad" diff --git a/app/assets/javascripts/vue_shared/components/diff_viewer/constants.js b/app/assets/javascripts/vue_shared/components/diff_viewer/constants.js new file mode 100644 index 00000000000..6c1840361af --- /dev/null +++ b/app/assets/javascripts/vue_shared/components/diff_viewer/constants.js @@ -0,0 +1,12 @@ +export const diffModes = { + replaced: 'replaced', + new: 'new', + deleted: 'deleted', + renamed: 'renamed', +}; + +export const imageViewMode = { + twoup: 'twoup', + swipe: 'swipe', + onion: 'onion', +}; diff --git a/app/assets/javascripts/vue_shared/components/diff_viewer/diff_viewer.vue b/app/assets/javascripts/vue_shared/components/diff_viewer/diff_viewer.vue index b1e8ba07b02..4bcf41f0a3c 100644 --- a/app/assets/javascripts/vue_shared/components/diff_viewer/diff_viewer.vue +++ b/app/assets/javascripts/vue_shared/components/diff_viewer/diff_viewer.vue @@ -56,7 +56,9 @@ export default { </script> <template> - <div class="diff-file preview-container"> + <div + class="diff-file preview-container" + v-if="viewer"> <component :is="viewer" :diff-mode="diffMode" diff --git a/app/assets/javascripts/vue_shared/components/diff_viewer/viewers/image_diff/onion_skin_viewer.vue b/app/assets/javascripts/vue_shared/components/diff_viewer/viewers/image_diff/onion_skin_viewer.vue index 6dbbf4dbe50..102778a3844 100644 --- a/app/assets/javascripts/vue_shared/components/diff_viewer/viewers/image_diff/onion_skin_viewer.vue +++ b/app/assets/javascripts/vue_shared/components/diff_viewer/viewers/image_diff/onion_skin_viewer.vue @@ -64,11 +64,9 @@ export default { }, startDrag() { this.dragging = true; - document.body.style.userSelect = 'none'; }, stopDrag() { this.dragging = false; - document.body.style.userSelect = ''; }, prepareOnionSkin() { if (this.onionOldImgInfo && this.onionNewImgInfo) { @@ -125,7 +123,11 @@ export default { <div class="onion-skin view"> <div class="onion-skin-frame" - :style="{ 'width': pixeliseValue(onionMaxWidth), 'height': pixeliseValue(onionMaxHeight) }"> + :style="{ + 'width': pixeliseValue(onionMaxWidth), + 'height': pixeliseValue(onionMaxHeight), + 'user-select': dragging === true ? 'none' : '', + }"> <div class="frame deleted" :style="{ 'width': pixeliseValue(onionMaxWidth), 'height': pixeliseValue(onionMaxHeight) }"> diff --git a/app/assets/javascripts/vue_shared/components/diff_viewer/viewers/image_diff/swipe_viewer.vue b/app/assets/javascripts/vue_shared/components/diff_viewer/viewers/image_diff/swipe_viewer.vue index 4c6b13b1434..57f1c095922 100644 --- a/app/assets/javascripts/vue_shared/components/diff_viewer/viewers/image_diff/swipe_viewer.vue +++ b/app/assets/javascripts/vue_shared/components/diff_viewer/viewers/image_diff/swipe_viewer.vue @@ -36,7 +36,7 @@ export default { beforeDestroy() { window.removeEventListener('resize', this.resizeThrottled, false); document.body.removeEventListener('mouseup', this.stopDrag); - this.$refs.swipeBar.removeEventListener('mousedown', this.startDrag); + document.body.removeEventListener('mousemove', this.dragMove); }, mounted() { this.resizeThrottled = _.throttle(this.resize, 400); @@ -44,29 +44,29 @@ export default { }, methods: { pixeliseValue, - initDraggable(el, padding, callback) { - const offsetEl = el.parentNode; - - const dragMove = e => { - if (!this.dragging) return; - const left = e.pageX - offsetEl.getBoundingClientRect().left; - callback(e, left); - }; - - el.addEventListener('mousedown', this.startDrag); - - document.body.removeEventListener('mouseup', dragMove); + dragMove(e) { + if (!this.dragging) return; + let leftValue = e.pageX - this.$refs.swipeBar.parentNode.getBoundingClientRect().left; + const wrapPadding = parseInt(this.$refs.swipeWrap.style.right.replace('px', ''), 10) || 10; + const { clientWidth } = this.$refs.swipeFrame; + if (leftValue <= 0) { + leftValue = 0; + } else if (leftValue > clientWidth - wrapPadding * 2) { + leftValue = clientWidth - wrapPadding * 2; + } - document.body.addEventListener('mouseup', this.stopDrag); - document.body.addEventListener('mousemove', dragMove); + this.swipeWrapWidth = this.swipeMaxWidth - leftValue; + this.swipeBarPos = leftValue; }, startDrag() { this.dragging = true; document.body.style.userSelect = 'none'; + document.body.addEventListener('mousemove', this.dragMove); }, stopDrag() { this.dragging = false; document.body.style.userSelect = ''; + document.body.removeEventListener('mousemove', this.dragMove); }, prepareSwipe() { if (this.swipeOldImgInfo && this.swipeNewImgInfo) { @@ -79,22 +79,7 @@ export default { this.swipeNewImgInfo.renderedHeight, ); - const wrapPadding = parseInt(this.$refs.swipeWrap.style.right.replace('px', ''), 10) || 10; - - const handleDrag = (e, left) => { - let leftValue = left; - if (leftValue <= 0) { - leftValue = 0; - } else if (leftValue > this.$refs.swipeFrame.clientWidth - wrapPadding * 2) { - leftValue = this.$refs.swipeFrame.clientWidth - wrapPadding * 2; - } - - this.swipeWrapWidth = this.swipeMaxWidth - leftValue; - this.swipeBarPos = leftValue; - }; - - handleDrag(null, 0); - this.initDraggable(this.$refs.swipeBar, wrapPadding, handleDrag); + document.body.addEventListener('mouseup', this.stopDrag); } }, swipeNewImgLoaded(imgInfo) { @@ -124,7 +109,10 @@ export default { <div class="swipe-frame" ref="swipeFrame" - :style="{ 'width': pixeliseValue(swipeMaxWidth), 'height': pixeliseValue(swipeMaxHeight) }"> + :style="{ + 'width': pixeliseValue(swipeMaxWidth), + 'height': pixeliseValue(swipeMaxHeight), + }"> <div class="deleted"> <image-viewer key="swipeOldImg" @@ -155,6 +143,8 @@ export default { <span class="swipe-bar" ref="swipeBar" + @mousedown="startDrag" + @mouseup="stopDrag" :style="{ 'left': pixeliseValue(swipeBarPos) }"> <span class="top-handle"></span> <span class="bottom-handle"></span> diff --git a/app/assets/javascripts/vue_shared/components/diff_viewer/viewers/image_diff_viewer.vue b/app/assets/javascripts/vue_shared/components/diff_viewer/viewers/image_diff_viewer.vue index b9838a7a9bd..63c913227f9 100644 --- a/app/assets/javascripts/vue_shared/components/diff_viewer/viewers/image_diff_viewer.vue +++ b/app/assets/javascripts/vue_shared/components/diff_viewer/viewers/image_diff_viewer.vue @@ -1,14 +1,10 @@ <script> +import { s__ } from '~/locale'; import ImageViewer from '../../content_viewer/viewers/image_viewer.vue'; import TwoUpViewer from './image_diff/two_up_viewer.vue'; import SwipeViewer from './image_diff/swipe_viewer.vue'; import OnionSkinViewer from './image_diff/onion_skin_viewer.vue'; - -const imageViewMode = { - twoup: 'twoup', - swipe: 'swipe', - onion: 'onion', -}; +import { diffModes, imageViewMode } from '../constants'; export default { components: { @@ -46,6 +42,7 @@ export default { this.mode = newMode; }, }, + diffModes, imageViewMode, }; </script> @@ -54,7 +51,7 @@ export default { <div class="diff-file-container"> <div class="diff-viewer" - v-if="diffMode === 'replaced'"> + v-if="diffMode === $options.diffModes.replaced"> <div class="image js-replaced-image"> <two-up-viewer v-if="mode === $options.imageViewMode.twoup" @@ -69,26 +66,32 @@ export default { <div class="view-modes"> <ul class="view-modes-menu"> <li - :class="{ 'active': mode === $options.imageViewMode.twoup }" + :class="{ + active: mode === $options.imageViewMode.twoup + }" @click="changeMode($options.imageViewMode.twoup)"> - {{ __('2-up') }} + {{ s__('ImageDiffViewer|2-up') }} </li> <li - :class="{ 'active': mode === $options.imageViewMode.swipe }" + :class="{ + active: mode === $options.imageViewMode.swipe + }" @click="changeMode($options.imageViewMode.swipe)"> - {{ __('Swipe') }} + {{ s__('ImageDiffViewer|Swipe') }} </li> <li - :class="{ 'active': mode === $options.imageViewMode.onion }" + :class="{ + active: mode === $options.imageViewMode.onion + }" @click="changeMode($options.imageViewMode.onion)"> - {{ __('Onion skin') }} + {{ s__('ImageDiffViewer|Onion skin') }} </li> </ul> </div> <div class="note-container"></div> </div> <div - v-else-if="diffMode==='new'" + v-else-if="diffMode === $options.diffModes.new" class="diff-viewer added"> <image-viewer :path="newPath" diff --git a/app/assets/stylesheets/framework/files.scss b/app/assets/stylesheets/framework/files.scss index c34612c149a..f060254777c 100644 --- a/app/assets/stylesheets/framework/files.scss +++ b/app/assets/stylesheets/framework/files.scss @@ -424,11 +424,11 @@ span.idiff { max-height: 70vh; } - .isZoomable { + .is-zoomable { cursor: pointer; cursor: zoom-in; - &.isZoomed { + &.is-zoomed { cursor: pointer; cursor: zoom-out; max-width: none; diff --git a/spec/javascripts/vue_shared/components/diff_viewer/viewers/image_diff_viewer_spec.js b/spec/javascripts/vue_shared/components/diff_viewer/viewers/image_diff_viewer_spec.js index e189913c4cd..26bc7472894 100644 --- a/spec/javascripts/vue_shared/components/diff_viewer/viewers/image_diff_viewer_spec.js +++ b/spec/javascripts/vue_shared/components/diff_viewer/viewers/image_diff_viewer_spec.js @@ -5,7 +5,6 @@ import { GREEN_BOX_IMAGE_URL, RED_BOX_IMAGE_URL } from 'spec/test_constants'; describe('ImageDiffViewer', () => { let vm; - let mock; function createComponent(props) { const ImageDiffViewer = Vue.extend(imageDiffViewer); @@ -43,7 +42,6 @@ describe('ImageDiffViewer', () => { afterEach(() => { vm.$destroy(); - if (mock) mock.restore(); }); it('renders image diff for replaced', done => { diff --git a/spec/javascripts/vue_shared/components/lib/utils/dom_utils_spec.js b/spec/javascripts/vue_shared/components/lib/utils/dom_utils_spec.js index df6d39807bf..2388660b0c2 100644 --- a/spec/javascripts/vue_shared/components/lib/utils/dom_utils_spec.js +++ b/spec/javascripts/vue_shared/components/lib/utils/dom_utils_spec.js @@ -2,7 +2,7 @@ import * as domUtils from '~/vue_shared/components/lib/utils/dom_utils'; describe('domUtils', () => { describe('pixeliseValue', () => { - it('should add px to a given NUmber', () => { + it('should add px to a given Number', () => { expect(domUtils.pixeliseValue(12)).toEqual('12px'); }); |