debian-mirror-gitlab/app/assets/javascripts/ide/components/repo_file.vue

226 lines
5.8 KiB
Vue
Raw Normal View History

2018-05-09 12:01:36 +05:30
<script>
2018-10-15 14:42:47 +05:30
import { mapActions, mapGetters } from 'vuex';
import { n__, __, sprintf } from '~/locale';
import tooltip from '~/vue_shared/directives/tooltip';
import SkeletonLoadingContainer from '~/vue_shared/components/skeleton_loading_container.vue';
import Icon from '~/vue_shared/components/icon.vue';
import FileIcon from '~/vue_shared/components/file_icon.vue';
2018-05-09 12:01:36 +05:30
import router from '../ide_router';
2018-10-15 14:42:47 +05:30
import NewDropdown from './new_dropdown/index.vue';
import FileStatusIcon from './repo_file_status_icon.vue';
import ChangedFileIcon from './changed_file_icon.vue';
import MrFileIcon from './mr_file_icon.vue';
2018-05-09 12:01:36 +05:30
export default {
name: 'RepoFile',
2018-10-15 14:42:47 +05:30
directives: {
tooltip,
},
2018-05-09 12:01:36 +05:30
components: {
2018-10-15 14:42:47 +05:30
SkeletonLoadingContainer,
NewDropdown,
FileStatusIcon,
FileIcon,
ChangedFileIcon,
MrFileIcon,
Icon,
2018-05-09 12:01:36 +05:30
},
props: {
file: {
type: Object,
required: true,
},
level: {
type: Number,
required: true,
},
2018-11-18 11:00:15 +05:30
},
data() {
return {
mouseOver: false,
};
2018-05-09 12:01:36 +05:30
},
computed: {
2018-10-15 14:42:47 +05:30
...mapGetters([
'getChangesInFolder',
'getUnstagedFilesCountForPath',
'getStagedFilesCountForPath',
]),
folderUnstagedCount() {
return this.getUnstagedFilesCountForPath(this.file.path);
},
folderStagedCount() {
return this.getStagedFilesCountForPath(this.file.path);
},
changesCount() {
return this.getChangesInFolder(this.file.path);
},
folderChangesTooltip() {
if (this.changesCount === 0) return undefined;
if (this.folderUnstagedCount > 0 && this.folderStagedCount === 0) {
return n__('%d unstaged change', '%d unstaged changes', this.folderUnstagedCount);
} else if (this.folderUnstagedCount === 0 && this.folderStagedCount > 0) {
return n__('%d staged change', '%d staged changes', this.folderStagedCount);
}
return sprintf(__('%{unstaged} unstaged and %{staged} staged changes'), {
unstaged: this.folderUnstagedCount,
staged: this.folderStagedCount,
});
},
2018-05-09 12:01:36 +05:30
isTree() {
return this.file.type === 'tree';
},
isBlob() {
return this.file.type === 'blob';
},
levelIndentation() {
return {
marginLeft: `${this.level * 16}px`,
};
},
fileClass() {
return {
'file-open': this.isBlob && this.file.opened,
'file-active': this.isBlob && this.file.active,
folder: this.isTree,
'is-open': this.file.opened,
};
},
2018-10-15 14:42:47 +05:30
showTreeChangesCount() {
return this.isTree && this.changesCount > 0 && !this.file.opened;
},
showChangedFileIcon() {
return this.file.changed || this.file.tempFile || this.file.staged;
},
2018-05-09 12:01:36 +05:30
},
2018-11-08 19:23:39 +05:30
mounted() {
if (this.hasPathAtCurrentRoute()) {
this.scrollIntoView(true);
}
},
2018-05-09 12:01:36 +05:30
updated() {
if (this.file.type === 'blob' && this.file.active) {
2018-11-08 19:23:39 +05:30
this.scrollIntoView();
2018-05-09 12:01:36 +05:30
}
},
methods: {
2018-10-15 14:42:47 +05:30
...mapActions(['toggleTreeOpen']),
2018-05-09 12:01:36 +05:30
clickFile() {
// Manual Action if a tree is selected/opened
2018-11-08 19:23:39 +05:30
if (this.isTree && this.hasUrlAtCurrentRoute()) {
2018-05-09 12:01:36 +05:30
this.toggleTreeOpen(this.file.path);
}
2018-10-15 14:42:47 +05:30
router.push(`/project${this.file.url}`);
2018-05-09 12:01:36 +05:30
},
2018-11-08 19:23:39 +05:30
scrollIntoView(isInit = false) {
const block = isInit && this.isTree ? 'center' : 'nearest';
this.$el.scrollIntoView({
behavior: 'smooth',
block,
});
},
hasPathAtCurrentRoute() {
if (!this.$router || !this.$router.currentRoute) {
return false;
}
// - strip route up to "/-/" and ending "/"
const routePath = this.$router.currentRoute.path
.replace(/^.*?[/]-[/]/g, '')
.replace(/[/]$/g, '');
// - strip ending "/"
2018-11-18 11:00:15 +05:30
const filePath = this.file.path.replace(/[/]$/g, '');
2018-11-08 19:23:39 +05:30
return filePath === routePath;
},
hasUrlAtCurrentRoute() {
return this.$router.currentRoute.path === `/project${this.file.url}`;
},
2018-11-18 11:00:15 +05:30
toggleHover(over) {
this.mouseOver = over;
},
2018-05-09 12:01:36 +05:30
},
};
</script>
<template>
<div>
<div
:class="fileClass"
2018-11-08 19:23:39 +05:30
class="file"
role="button"
@click="clickFile"
2018-11-18 11:00:15 +05:30
@mouseover="toggleHover(true)"
@mouseout="toggleHover(false)"
2018-05-09 12:01:36 +05:30
>
<div
class="file-name"
>
<span
:style="levelIndentation"
2018-11-08 19:23:39 +05:30
class="ide-file-name str-truncated"
2018-05-09 12:01:36 +05:30
>
<file-icon
:file-name="file.name"
:loading="file.loading"
:folder="isTree"
:opened="file.opened"
:size="16"
/>
{{ file.name }}
<file-status-icon
:file="file"
/>
</span>
2018-11-08 19:23:39 +05:30
<span class="float-right ide-file-icon-holder">
2018-05-09 12:01:36 +05:30
<mr-file-icon
v-if="file.mrChange"
/>
2018-10-15 14:42:47 +05:30
<span
v-if="showTreeChangesCount"
class="ide-tree-changes"
>
{{ changesCount }}
<icon
v-tooltip
:title="folderChangesTooltip"
2018-11-08 19:23:39 +05:30
:size="12"
2018-10-15 14:42:47 +05:30
data-container="body"
data-placement="right"
name="file-modified"
2018-11-18 11:00:15 +05:30
css-classes="prepend-left-5 ide-file-modified"
2018-10-15 14:42:47 +05:30
/>
</span>
2018-05-09 12:01:36 +05:30
<changed-file-icon
2018-10-15 14:42:47 +05:30
v-else-if="showChangedFileIcon"
2018-05-09 12:01:36 +05:30
:file="file"
2018-10-15 14:42:47 +05:30
:show-tooltip="true"
:show-staged-icon="true"
:force-modified-icon="true"
2018-11-08 19:23:39 +05:30
class="float-right"
2018-05-09 12:01:36 +05:30
/>
</span>
<new-dropdown
2018-11-18 11:00:15 +05:30
:type="file.type"
2018-05-09 12:01:36 +05:30
:path="file.path"
2018-11-18 11:00:15 +05:30
:mouse-over="mouseOver"
2018-11-08 19:23:39 +05:30
class="float-right prepend-left-8"
2018-05-09 12:01:36 +05:30
/>
</div>
</div>
<template v-if="file.opened">
<repo-file
v-for="childFile in file.tree"
:key="childFile.key"
:file="childFile"
:level="level + 1"
/>
</template>
</div>
</template>