parent
af9cc234f2
commit
524ebff5d1
9 changed files with 285 additions and 15 deletions
|
@ -13,6 +13,7 @@ import CommitSection from './repo_commit_section.vue';
|
|||
import CommitForm from './commit_sidebar/form.vue';
|
||||
import IdeReview from './ide_review.vue';
|
||||
import SuccessMessage from './commit_sidebar/success_message.vue';
|
||||
import MergeRequestDropdown from './merge_requests/dropdown.vue';
|
||||
import { activityBarViews } from '../constants';
|
||||
|
||||
export default {
|
||||
|
@ -32,6 +33,7 @@ export default {
|
|||
CommitForm,
|
||||
IdeReview,
|
||||
SuccessMessage,
|
||||
MergeRequestDropdown,
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
|
@ -46,6 +48,7 @@ export default {
|
|||
'changedFiles',
|
||||
'stagedFiles',
|
||||
'lastCommitMsg',
|
||||
'currentMergeRequestId',
|
||||
]),
|
||||
...mapGetters(['currentProject', 'someUncommitedChanges']),
|
||||
showSuccessMessage() {
|
||||
|
@ -88,9 +91,12 @@ export default {
|
|||
</div>
|
||||
</template>
|
||||
<template v-else>
|
||||
<div class="context-header ide-context-header">
|
||||
<div class="context-header ide-context-header dropdown">
|
||||
<a
|
||||
:href="currentProject.web_url"
|
||||
href="#"
|
||||
role="button"
|
||||
@click.prevent
|
||||
data-toggle="dropdown"
|
||||
>
|
||||
<div
|
||||
v-if="currentProject.avatar_url"
|
||||
|
@ -114,19 +120,35 @@ export default {
|
|||
<div class="sidebar-context-title">
|
||||
{{ currentProject.name }}
|
||||
</div>
|
||||
<div
|
||||
class="sidebar-context-title ide-sidebar-branch-title"
|
||||
ref="branchId"
|
||||
v-tooltip
|
||||
:title="branchTooltipTitle"
|
||||
>
|
||||
<icon
|
||||
name="branch"
|
||||
css-classes="append-right-5"
|
||||
/>{{ currentBranchId }}
|
||||
<div class="d-flex">
|
||||
<div
|
||||
class="sidebar-context-title ide-sidebar-branch-title"
|
||||
ref="branchId"
|
||||
v-tooltip
|
||||
:title="branchTooltipTitle"
|
||||
>
|
||||
<icon
|
||||
name="branch"
|
||||
css-classes="append-right-5"
|
||||
/>{{ currentBranchId }}
|
||||
</div>
|
||||
<div
|
||||
v-if="currentMergeRequestId"
|
||||
class="sidebar-context-title ide-sidebar-branch-title prepend-left-8"
|
||||
>
|
||||
<icon
|
||||
name="git-merge"
|
||||
css-classes="append-right-5"
|
||||
/>!{{ currentMergeRequestId }}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<icon
|
||||
class="ml-auto"
|
||||
name="chevron-down"
|
||||
/>
|
||||
</a>
|
||||
<merge-request-dropdown />
|
||||
</div>
|
||||
<div class="multi-file-commit-panel-inner-scroll">
|
||||
<component
|
||||
|
|
|
@ -0,0 +1,78 @@
|
|||
<script>
|
||||
import { mapActions, mapState } from 'vuex';
|
||||
import Tabs from '../../../vue_shared/components/tabs/tabs';
|
||||
import Tab from '../../../vue_shared/components/tabs/tab.vue';
|
||||
import List from './list.vue';
|
||||
import { scopes } from '../../stores/modules/merge_requests/constants';
|
||||
|
||||
export default {
|
||||
components: {
|
||||
Tabs,
|
||||
Tab,
|
||||
List,
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
activeTabIndex: 0,
|
||||
};
|
||||
},
|
||||
computed: {
|
||||
...mapState('mergeRequests', ['isLoading', 'mergeRequests']),
|
||||
...mapState(['currentMergeRequestId']),
|
||||
tabScope() {
|
||||
return this.activeTabIndex === 0 ? scopes.createdByMe : scopes.assignedToMe;
|
||||
},
|
||||
},
|
||||
mounted() {
|
||||
this.fetchMergeRequests();
|
||||
},
|
||||
methods: {
|
||||
...mapActions('mergeRequests', ['fetchMergeRequests', 'setScope']),
|
||||
updateActiveTab(index) {
|
||||
this.activeTabIndex = index;
|
||||
|
||||
this.setScope(this.tabScope);
|
||||
this.fetchMergeRequests();
|
||||
},
|
||||
},
|
||||
};
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<div class="dropdown-menu">
|
||||
<tabs
|
||||
stop-propagation
|
||||
@changed="updateActiveTab"
|
||||
>
|
||||
<tab
|
||||
:title="__('Created by me')"
|
||||
active
|
||||
>
|
||||
<list
|
||||
v-if="activeTabIndex === 0"
|
||||
:is-loading="isLoading"
|
||||
:items="mergeRequests"
|
||||
:current-id="currentMergeRequestId"
|
||||
@search="fetchMergeRequests"
|
||||
/>
|
||||
</tab>
|
||||
<tab :title="__('Assigned to me')">
|
||||
<list
|
||||
v-if="activeTabIndex === 1"
|
||||
:is-loading="isLoading"
|
||||
:items="mergeRequests"
|
||||
:current-id="currentMergeRequestId"
|
||||
@search="fetchMergeRequests"
|
||||
/>
|
||||
</tab>
|
||||
</tabs>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<style scoped>
|
||||
.dropdown-menu {
|
||||
width: 400px;
|
||||
padding: 0;
|
||||
max-height: initial !important;
|
||||
}
|
||||
</style>
|
|
@ -0,0 +1,59 @@
|
|||
<script>
|
||||
import Icon from '../../../vue_shared/components/icon.vue';
|
||||
|
||||
export default {
|
||||
components: {
|
||||
Icon,
|
||||
},
|
||||
props: {
|
||||
item: {
|
||||
type: Object,
|
||||
required: true,
|
||||
},
|
||||
currentId: {
|
||||
type: String,
|
||||
required: true,
|
||||
},
|
||||
},
|
||||
computed: {
|
||||
isActive() {
|
||||
return this.item.iid === parseInt(this.currentId, 10);
|
||||
},
|
||||
pathWithID() {
|
||||
return `${this.item.projectPathWithNamespace}!${this.item.iid}`;
|
||||
},
|
||||
},
|
||||
methods: {
|
||||
clickItem() {
|
||||
this.$emit('click', this.item);
|
||||
},
|
||||
},
|
||||
};
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<button
|
||||
type="button"
|
||||
class="d-flex align-items-center"
|
||||
@click="clickItem"
|
||||
>
|
||||
<span
|
||||
class="d-flex append-right-default"
|
||||
style="min-width: 18px"
|
||||
>
|
||||
<icon
|
||||
v-if="isActive"
|
||||
name="mobile-issue-close"
|
||||
:size="18"
|
||||
/>
|
||||
</span>
|
||||
<span>
|
||||
<strong>
|
||||
{{ item.title }}
|
||||
</strong>
|
||||
<span class="d-block mt-1">
|
||||
{{ pathWithID }}
|
||||
</span>
|
||||
</span>
|
||||
</button>
|
||||
</template>
|
|
@ -0,0 +1,91 @@
|
|||
<script>
|
||||
import _ from 'underscore';
|
||||
import LoadingIcon from '../../../vue_shared/components/loading_icon.vue';
|
||||
import Item from './item.vue';
|
||||
|
||||
export default {
|
||||
components: {
|
||||
LoadingIcon,
|
||||
Item,
|
||||
},
|
||||
props: {
|
||||
isLoading: {
|
||||
type: Boolean,
|
||||
required: true,
|
||||
},
|
||||
items: {
|
||||
type: Array,
|
||||
required: true,
|
||||
},
|
||||
currentId: {
|
||||
type: String,
|
||||
required: true,
|
||||
},
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
search: '',
|
||||
};
|
||||
},
|
||||
watch: {
|
||||
isLoading() {
|
||||
this.focusSearch();
|
||||
},
|
||||
},
|
||||
methods: {
|
||||
viewMergeRequest(item) {
|
||||
this.$router.push(`/project/${item.projectPathWithNamespace}/merge_requests/${item.iid}`);
|
||||
},
|
||||
searchMergeRequests: _.debounce(function debounceSearch() {
|
||||
this.$emit('search', this.search);
|
||||
}, 250),
|
||||
focusSearch() {
|
||||
if (!this.isLoading) {
|
||||
this.$nextTick(() => {
|
||||
this.$refs.searchInput.focus();
|
||||
});
|
||||
}
|
||||
},
|
||||
},
|
||||
};
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<div>
|
||||
<loading-icon
|
||||
class="mt-3 mb-3"
|
||||
v-if="isLoading"
|
||||
size="2"
|
||||
/>
|
||||
<template v-else>
|
||||
<div class="dropdown-input mt-3 pb-3 mb-3 border-bottom">
|
||||
<input
|
||||
type="search"
|
||||
class="dropdown-input-field"
|
||||
placeholder="Search merge requests"
|
||||
v-model="search"
|
||||
@input="searchMergeRequests"
|
||||
ref="searchInput"
|
||||
/>
|
||||
<i
|
||||
aria-hidden="true"
|
||||
class="fa fa-search dropdown-input-search"
|
||||
></i>
|
||||
</div>
|
||||
<div class="dropdown-content">
|
||||
<ul class="mb-3">
|
||||
<li
|
||||
v-for="item in items"
|
||||
:key="item.id"
|
||||
>
|
||||
<item
|
||||
:item="item"
|
||||
:current-id="currentId"
|
||||
@click="viewMergeRequest"
|
||||
/>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
</template>
|
||||
</div>
|
||||
</template>
|
|
@ -22,4 +22,6 @@ export const fetchMergeRequests = ({ dispatch, state: { scope, state } }, search
|
|||
|
||||
export const resetMergeRequests = ({ commit }) => commit(types.RESET_MERGE_REQUESTS);
|
||||
|
||||
export const setScope = ({ commit }, scope) => commit(types.SET_SCOPE, scope);
|
||||
|
||||
export default () => {};
|
||||
|
|
|
@ -3,3 +3,5 @@ export const RECEIVE_MERGE_REQUESTS_ERROR = 'RECEIVE_MERGE_REQUESTS_ERROR';
|
|||
export const RECEIVE_MERGE_REQUESTS_SUCCESS = 'RECEIVE_MERGE_REQUESTS_SUCCESS';
|
||||
|
||||
export const RESET_MERGE_REQUESTS = 'RESET_MERGE_REQUESTS';
|
||||
|
||||
export const SET_SCOPE = 'SET_SCOPE';
|
||||
|
|
|
@ -23,4 +23,7 @@ export default {
|
|||
[types.RESET_MERGE_REQUESTS](state) {
|
||||
state.mergeRequests = [];
|
||||
},
|
||||
[types.SET_SCOPE](state, scope) {
|
||||
state.scope = scope;
|
||||
},
|
||||
};
|
||||
|
|
|
@ -3,6 +3,6 @@ import { scopes, states } from './constants';
|
|||
export default () => ({
|
||||
isLoading: false,
|
||||
mergeRequests: [],
|
||||
scope: scopes.assignedToMe,
|
||||
scope: scopes.createdByMe,
|
||||
state: states.opened,
|
||||
});
|
||||
|
|
|
@ -1,4 +1,11 @@
|
|||
export default {
|
||||
props: {
|
||||
stopPropagation: {
|
||||
type: Boolean,
|
||||
required: false,
|
||||
default: false,
|
||||
},
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
currentIndex: 0,
|
||||
|
@ -13,11 +20,17 @@ export default {
|
|||
this.tabs = this.$children.filter(child => child.isTab);
|
||||
this.currentIndex = this.tabs.findIndex(tab => tab.localActive);
|
||||
},
|
||||
setTab(index) {
|
||||
setTab(e, index) {
|
||||
if (this.stopPropagation) {
|
||||
e.stopPropagation();
|
||||
}
|
||||
|
||||
this.tabs[this.currentIndex].localActive = false;
|
||||
this.tabs[index].localActive = true;
|
||||
|
||||
this.currentIndex = index;
|
||||
|
||||
this.$emit('changed', this.currentIndex);
|
||||
},
|
||||
},
|
||||
render(h) {
|
||||
|
@ -36,7 +49,7 @@ export default {
|
|||
href: '#',
|
||||
},
|
||||
on: {
|
||||
click: () => this.setTab(i),
|
||||
click: e => this.setTab(e, i),
|
||||
},
|
||||
},
|
||||
tab.$slots.title || tab.title,
|
||||
|
|
Loading…
Reference in a new issue