Commit fe43c8aa authored by Kushal Pandya's avatar Kushal Pandya Committed by Jarka Košanová

Add initial frontend for attaching child epics

Adds backstage support to related issues app
to enable attaching epics to an epic
parent 68e1a43d
......@@ -82,6 +82,10 @@ export default {
type: Object,
required: true,
},
epicLinksEndpoint: {
type: String,
required: true,
},
issueLinksEndpoint: {
type: String,
required: true,
......@@ -146,6 +150,10 @@ export default {
type: Array,
required: true,
},
parentEpic: {
type: Object,
required: true,
},
participants: {
type: Array,
required: true,
......@@ -293,6 +301,7 @@ export default {
:initial-participants="participants"
:initial-subscribed="subscribed"
:initial-todo-exists="todoExists"
:parent-epic="parentEpic"
:namespace="namespace"
:update-path="updateEndpoint"
:labels-path="labelsPath"
......@@ -302,6 +311,13 @@ export default {
:labels-web-url="labelsWebUrl"
:epics-web-url="epicsWebUrl"
/>
<related-issues-root
:endpoint="epicLinksEndpoint"
:can-admin="canAdmin"
:can-reorder="canAdmin"
:allow-auto-complete="false"
title="Epics"
/>
<related-issues-root
:endpoint="issueLinksEndpoint"
:can-admin="canAdmin"
......
......@@ -15,6 +15,16 @@ export default () => {
Cookies.set('collapsed_gutter', true);
}
// TODO remove once API provides proper data
initialData.epicLinksEndpoint = '/';
metaData.parentEpic = {
id: 7,
title: 'Epic with out of range end date',
url: '/groups/gitlab-org/-/epics/7',
human_readable_timestamp: '<strong>30</strong> days remaining',
human_readable_end_date: 'Dec 28, 2018',
};
const props = Object.assign({}, initialData, metaData, el.dataset);
return new Vue({
......
......@@ -12,6 +12,7 @@ import SidebarTodo from '~/sidebar/components/todo_toggle/todo.vue';
import SidebarCollapsedGroupedDatePicker from '~/vue_shared/components/sidebar/collapsed_grouped_date_picker.vue';
import ToggleSidebar from '~/vue_shared/components/sidebar/toggle_sidebar.vue';
import SidebarLabelsSelect from '~/vue_shared/components/sidebar/labels_select/base.vue';
import SidebarItemEpic from 'ee/sidebar/components/sidebar_item_epic.vue';
import { parseBoolean } from '~/lib/utils/common_utils';
import eventHub from '../../event_hub';
import SidebarDatePicker from './sidebar_date_picker.vue';
......@@ -33,6 +34,7 @@ export default {
SidebarDatePicker,
SidebarCollapsedGroupedDatePicker,
SidebarLabelsSelect,
SidebarItemEpic,
SidebarParticipants,
SidebarSubscriptions,
},
......@@ -116,6 +118,10 @@ export default {
type: Boolean,
required: true,
},
parentEpic: {
type: Object,
required: true,
},
namespace: {
type: String,
required: false,
......@@ -462,7 +468,7 @@ export default {
<div class="issuable-sidebar js-issuable-update">
<div class="block issuable-sidebar-header">
<span class="issuable-header-text hide-collapsed float-left">{{ __('Todo') }}</span>
<toggle-sidebar :collapsed="collapsed" css-classes="float-right" @toggle="toggleSidebar" />
<toggle-sidebar :collapsed="collapsed" css-classes="float-right" @toggle="toggleSidebar"/>
<sidebar-todo
v-if="!collapsed"
:collapsed="collapsed"
......@@ -547,9 +553,11 @@ export default {
@onLabelClick="handleLabelClick"
@onDropdownClose="handleDropdownClose"
@toggleCollapse="toggleSidebarRevealLabelsDropdown"
>{{ __('None') }}</sidebar-labels-select
>
<sidebar-participants :participants="initialParticipants" @toggleCollapse="toggleSidebar" />
>{{ __('None') }}</sidebar-labels-select>
<div class="block parent-epic">
<sidebar-item-epic :block-title="__('Parent epic')" :initial-epic="parentEpic"/>
</div>
<sidebar-participants :participants="initialParticipants" @toggleCollapse="toggleSidebar"/>
<sidebar-subscriptions
:loading="savingSubscription"
:subscribed="store.subscribed"
......
......@@ -13,23 +13,43 @@ export default {
components: {
GlLoadingIcon,
},
props: {
blockTitle: {
type: String,
required: false,
default: __('Epic'),
},
initialEpic: {
type: Object,
required: false,
default: () => {},
},
},
data() {
let store = {};
if (!this.initialEpic) {
store = new Store();
}
return {
store: new Store(),
store,
};
},
computed: {
isLoading() {
return this.store.isFetching.epic;
return this.initialEpic ? false : this.store.isFetching.epic;
},
epicIcon() {
return spriteIcon('epic');
},
epic() {
return this.initialEpic || this.store.epic;
},
epicUrl() {
return this.store.epic.url;
return this.epic.url;
},
epicTitle() {
return this.store.epic.title;
return this.epic.title;
},
hasEpic() {
return this.epicUrl && this.epicTitle;
......@@ -43,13 +63,13 @@ export default {
}
let tooltipTitle = this.epicTitle;
if (this.store.epic.human_readable_end_date || this.store.epic.human_readable_timestamp) {
if (this.epic.human_readable_end_date || this.epic.human_readable_timestamp) {
tooltipTitle += '<br />';
tooltipTitle += this.store.epic.human_readable_end_date
? `${this.store.epic.human_readable_end_date} `
tooltipTitle += this.epic.human_readable_end_date
? `${this.epic.human_readable_end_date} `
: '';
tooltipTitle += this.store.epic.human_readable_timestamp
? `(${this.store.epic.human_readable_timestamp})`
tooltipTitle += this.epic.human_readable_timestamp
? `(${this.epic.human_readable_timestamp})`
: '';
}
......@@ -71,15 +91,15 @@ export default {
data-boundary="viewport"
>
<div v-html="epicIcon"></div>
<span v-if="!isLoading" class="collapse-truncated-title"> {{ collapsedTitle }} </span>
<span v-if="!isLoading" class="collapse-truncated-title">{{ collapsedTitle }}</span>
</div>
<div class="title hide-collapsed">
Epic
<gl-loading-icon v-if="isLoading" :inline="true" />
{{ blockTitle }}
<gl-loading-icon v-if="isLoading" :inline="true"/>
</div>
<div v-if="!isLoading" class="value hide-collapsed">
<a v-if="hasEpic" :href="epicUrl" class="bold"> {{ epicTitle }} </a>
<span v-else class="no-value"> None </span>
<a v-if="hasEpic" :href="epicUrl" class="bold">{{ epicTitle }}</a>
<span v-else class="no-value">None</span>
</div>
</div>
</template>
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