Commit b3f45856 authored by David O'Regan's avatar David O'Regan Committed by Natalia Tepluhina

Highlight currently focused/viewed file in file tree

parent 5a76d154
......@@ -58,6 +58,9 @@ export default {
hasDiff() {
return hasDiff(this.file);
},
isActive() {
return this.currentDiffFileId === this.file.file_hash;
},
isFileTooLarge() {
return this.file.viewer.error === diffViewerErrors.too_large;
},
......@@ -143,7 +146,7 @@ export default {
<div
:id="file.file_hash"
:class="{
'is-active': currentDiffFileId === file.file_hash,
'is-active': isActive,
}"
class="diff-file file-holder"
>
......@@ -153,6 +156,7 @@ export default {
:collapsible="true"
:expanded="!isCollapsed"
:add-merge-request-buttons="true"
:is-active="isActive"
class="js-file-title file-title"
@toggleFile="handleToggle"
@showForkMessage="showForkMessage"
......
......@@ -55,6 +55,11 @@ export default {
type: Boolean,
required: true,
},
isActive: {
type: Boolean,
required: false,
default: false,
},
},
computed: {
...mapGetters('diffs', ['diffHasExpandedDiscussions', 'diffHasDiscussions']),
......@@ -158,6 +163,9 @@ export default {
<div
ref="header"
class="js-file-title file-title file-title-flex-parent"
:class="{
'is-active': isActive,
}"
@click.self="handleToggleFile"
>
<div class="file-header-content">
......
......@@ -26,7 +26,7 @@ export default {
};
},
computed: {
...mapState('diffs', ['tree', 'renderTreeList']),
...mapState('diffs', ['tree', 'renderTreeList', 'currentDiffFileId', 'viewedDiffFileIds']),
...mapGetters('diffs', ['allBlobs']),
filteredTreeList() {
const search = this.search.toLowerCase().trim();
......@@ -96,6 +96,8 @@ export default {
:level="0"
:hide-file-stats="hideFileStats"
:file-row-component="$options.DiffFileRow"
:active-file="currentDiffFileId"
:viewed-files="viewedDiffFileIds"
@toggleTreeOpen="toggleTreeOpen"
@clickFile="scrollToFile"
/>
......
......@@ -26,6 +26,7 @@ export default () => ({
showTreeList: true,
currentDiffFileId: '',
projectPath: '',
viewedDiffFileIds: [],
commentForms: [],
highlightedRow: null,
renderTreeList: true,
......
......@@ -284,6 +284,9 @@ export default {
},
[types.UPDATE_CURRENT_DIFF_FILE_ID](state, fileId) {
state.currentDiffFileId = fileId;
if (!state.viewedDiffFileIds.includes(fileId)) {
state.viewedDiffFileIds = [fileId, ...state.viewedDiffFileIds];
}
},
[types.OPEN_DIFF_FILE_COMMENT_FORM](state, formData) {
state.commentForms.push({
......
......@@ -18,6 +18,16 @@ export default {
type: Number,
required: true,
},
activeFile: {
type: String,
required: false,
default: '',
},
viewedFiles: {
type: Array,
required: false,
default: () => [],
},
},
computed: {
isTree() {
......@@ -34,8 +44,8 @@ export default {
fileClass() {
return {
'file-open': this.isBlob && this.file.opened,
'is-active': this.isBlob && this.file.active,
folder: this.isTree,
'is-active': this.isBlob && (this.file.active || this.activeFile === this.file.fileHash),
'is-viewed': this.isBlob && this.viewedFiles.includes(this.file.fileHash),
'is-open': this.file.opened,
};
},
......@@ -107,15 +117,23 @@ export default {
v-else
:class="fileClass"
:title="file.name"
class="file-row"
class="file-row text-left px-1 py-2 ml-n2 d-flex align-items-center"
role="button"
@click="clickFile"
@mouseleave="$emit('mouseleave', $event)"
>
<div class="file-row-name-container">
<span ref="textOutput" :style="levelIndentation" class="file-row-name str-truncated">
<div class="file-row-name-container w-100 d-flex align-items-center">
<span
ref="textOutput"
:style="levelIndentation"
class="file-row-name str-truncated d-inline-block"
:class="[
{ 'folder font-weight-normal': isTree },
fileClass['is-viewed'] ? 'font-weight-normal' : 'font-weight-bold',
]"
>
<file-icon
class="file-row-icon"
class="file-row-icon align-middle mr-1"
:class="{ 'text-secondary': file.type === 'tree' }"
:file-name="file.name"
:loading="file.loading"
......@@ -132,14 +150,8 @@ export default {
<style>
.file-row {
display: flex;
align-items: center;
height: 32px;
padding: 4px 8px;
margin-left: -8px;
margin-right: -8px;
border-radius: 3px;
text-align: left;
cursor: pointer;
}
......@@ -157,24 +169,15 @@ export default {
}
.file-row-name-container {
display: flex;
width: 100%;
align-items: center;
overflow: visible;
}
.file-row-name {
display: inline-block;
flex: 1;
max-width: inherit;
height: 19px;
height: 20px;
line-height: 16px;
text-overflow: ellipsis;
white-space: nowrap;
}
.file-row-name .file-row-icon {
margin-right: 2px;
vertical-align: middle;
}
</style>
......@@ -69,6 +69,11 @@
}
}
.file-title.is-active,
.file-title-flex-parent.is-active {
background-color: $gray-200;
}
@media (min-width: map-get($grid-breakpoints, md)) {
&.conflict .file-title,
&.conflict .file-title-flex-parent {
......
---
title: Highlight currently focused/viewed file in file tree
merge_request: 27703
author:
type: changed
......@@ -61,6 +61,7 @@ describe('DiffFileHeader component', () => {
const findTitleLink = () => wrapper.find({ ref: 'titleWrapper' });
const findExpandButton = () => wrapper.find({ ref: 'expandDiffToFullFileButton' });
const findFileActions = () => wrapper.find('.file-actions');
const findActiveHeader = () => wrapper.find('.is-active');
const findModeChangedLine = () => wrapper.find({ ref: 'fileMode' });
const findLfsLabel = () => wrapper.find('.label-lfs');
const findToggleDiscussionsButton = () => wrapper.find({ ref: 'toggleDiscussionsButton' });
......@@ -143,6 +144,11 @@ describe('DiffFileHeader component', () => {
expect(wrapper.find(ClipboardButton).exists()).toBe(true);
});
it('contains a active header class if this is the active file header', () => {
createComponent({ isActive: true });
expect(findActiveHeader().exists()).toBe(true);
});
describe('for submodule', () => {
const submoduleDiffFile = {
...diffFile,
......
......@@ -72,6 +72,19 @@ describe('File row component', () => {
});
});
it('is marked as viewed if clicked', () => {
createComponent({
file: {
...file(),
type: 'blob',
fileHash: '#123456789',
},
level: 0,
viewedFiles: ['#123456789'],
});
expect(wrapper.classes()).toContain('is-viewed');
});
it('indents row based on level', () => {
createComponent({
file: file('t4'),
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment