diff options
author | Fatih Acet <acetfatih@gmail.com> | 2018-03-19 15:46:33 +0300 |
---|---|---|
committer | Fatih Acet <acetfatih@gmail.com> | 2018-03-19 15:46:33 +0300 |
commit | e0c1a173921b775c467448da5e5dade8a6f9f166 (patch) | |
tree | 0e61cdad34c78469fbf4ea319e4afc78d330b75b | |
parent | e1739e47c5664c93c66dd58ded59f9d79cd8a426 (diff) | |
download | gitlab-ce-_mr-refactor-part-11.tar.gz |
MR Diffs Refactor Part 11: Diffs app index and app components._mr-refactor-part-11
-rw-r--r-- | app/assets/javascripts/diffs/components/app.vue | 83 | ||||
-rw-r--r-- | app/assets/javascripts/diffs/constants.js | 13 | ||||
-rw-r--r-- | app/assets/javascripts/diffs/index.js | 27 | ||||
-rw-r--r-- | app/assets/javascripts/diffs/mixins/diff_content.js | 76 |
4 files changed, 199 insertions, 0 deletions
diff --git a/app/assets/javascripts/diffs/components/app.vue b/app/assets/javascripts/diffs/components/app.vue new file mode 100644 index 00000000000..fde261a4aa7 --- /dev/null +++ b/app/assets/javascripts/diffs/components/app.vue @@ -0,0 +1,83 @@ +<script> +import { mapState, mapActions } from 'vuex'; +import loadingIcon from '../../vue_shared/components/loading_icon.vue'; +import compareVersions from './compare_versions.vue'; +import changedFiles from './changed_files.vue'; +import diffFile from './diff_file.vue'; + +export default { + name: 'DiffsApp', + components: { + loadingIcon, + compareVersions, + changedFiles, + diffFile, + }, + props: { + endpoint: { + type: String, + required: true, + }, + shouldShow: { + type: Boolean, + required: false, + default: false, + }, + }, + data() { + return { + activeFile: '', + }; + }, + computed: { + ...mapState({ + isLoading: state => state.diffs.isLoading, + diffFiles: state => state.diffs.diffFiles, + }), + }, + mounted() { + this.setEndpoint(this.endpoint); + this.fetchDiffFiles(); // TODO: @fatihacet Error handling + }, + methods: { + ...mapActions(['setEndpoint', 'fetchDiffFiles']), + setActive(filePath) { + this.activeFile = filePath; + }, + unsetActive(filePath) { + if (this.activeFile === filePath) { + this.activeFile = ''; + } + }, + }, +}; +</script> + +<template> + <div v-if="shouldShow"> + <loading-icon + v-if="isLoading" + size="3" + /> + <div + v-else + id="diffs" + class="diffs tab-pane" + > + <compare-versions /> + <changed-files + :diff-files="diffFiles" + :active-file="activeFile" + /> + <div class="files"> + <diff-file + @setActive="setActive(file.filePath)" + @unsetActive="unsetActive(file.filePath)" + v-for="file in diffFiles" + :key="file.newPath" + :file="file" + /> + </div> + </div> + </div> +</template> diff --git a/app/assets/javascripts/diffs/constants.js b/app/assets/javascripts/diffs/constants.js new file mode 100644 index 00000000000..fa8cccbc46c --- /dev/null +++ b/app/assets/javascripts/diffs/constants.js @@ -0,0 +1,13 @@ +export const INLINE_DIFF_VIEW_TYPE = 'inline'; +export const PARALLEL_DIFF_VIEW_TYPE = 'parallel'; +export const MATCH_LINE_TYPE = 'match'; +export const DIFF_VIEW_COOKIE_NAME = 'diff_view'; +export const EMPTY_CELL_TYPE = 'empty-cell'; +export const LINE_HOVER_CLASS_NAME = 'is-over'; +export const COMMENT_FORM_TYPE = 'commentForm'; +export const LINE_POSITION_LEFT = 'left'; +export const LINE_POSITION_RIGHT = 'right'; +export const TEXT_DIFF_POSITION_TYPE = 'text'; +export const DIFF_NOTE_TYPE = 'DiffNote'; +export const NEW_LINE_TYPE = 'new'; +export const OLD_LINE_TYPE = 'old'; diff --git a/app/assets/javascripts/diffs/index.js b/app/assets/javascripts/diffs/index.js new file mode 100644 index 00000000000..f0038091aa5 --- /dev/null +++ b/app/assets/javascripts/diffs/index.js @@ -0,0 +1,27 @@ +import Vue from 'vue'; +import diffsApp from './components/app.vue'; + +document.addEventListener( + 'DOMContentLoaded', + () => + new Vue({ + el: '#js-diffs-app', + components: { + diffsApp, + }, + data() { + const dataset = document.querySelector(this.$options.el).dataset; + + return { + endpoint: dataset.path, + }; + }, + render(createElement) { + return createElement('diffs-app', { + props: { + endpoint: this.endpoint, + }, + }); + }, + }), +); diff --git a/app/assets/javascripts/diffs/mixins/diff_content.js b/app/assets/javascripts/diffs/mixins/diff_content.js new file mode 100644 index 00000000000..11db6a10a3e --- /dev/null +++ b/app/assets/javascripts/diffs/mixins/diff_content.js @@ -0,0 +1,76 @@ +import { mapGetters, mapActions } from 'vuex'; +import diffDiscussions from '../components/diff_discussions.vue'; +import diffLineGutterContent from '../components/diff_line_gutter_content.vue'; +import diffLineNoteForm from '../components/diff_line_note_form.vue'; + +export default { + props: { + diffFile: { + type: Object, + required: true, + }, + diffLines: { + type: Array, + required: true, + }, + }, + data() { + return { + hoveredLineCode: undefined, + hoveredSection: undefined, + }; + }, + components: { + diffDiscussions, + diffLineNoteForm, + diffLineGutterContent, + }, + computed: { + ...mapGetters(['discussionsByLineCode']), + userColorScheme() { + return window.gon.user_color_scheme; + }, + normalizedDiffLines() { + return this.diffLines.map(line => { + if (line.richText) { + return this.trimFirstChar(line); + } + + if (line.left) { + Object.assign(line, { left: this.trimFirstChar(line.left) }); + } + + if (line.right) { + Object.assign(line, { right: this.trimFirstChar(line.right) }); + } + + return line; + }); + }, + }, + methods: { + ...mapActions(['showCommentForm', 'cancelCommentForm']), + trimFirstChar(line) { + if (!line.richText) { + return line; + } + + const firstChar = line.richText.charAt(0); + + if (firstChar === ' ' || firstChar === '+' || firstChar === '-') { + Object.assign(line, { + richText: line.richText.substring(1), + }); + } + + return line; + }, + handleShowCommentForm({ lineCode, linePosition }) { + this.showCommentForm({ + diffLines: this.diffLines, + lineCode, + linePosition, + }); + }, + }, +}; |