Commit 5e223913 authored by Mike Greiling's avatar Mike Greiling Committed by Simon Knox

Remove orphaned vue components

parent 96f06f05
// This is a true violation of @gitlab/no-runtime-template-compiler, as it
// relies on app/views/shared/boards/components/_sidebar.html.haml for its
// template.
/* eslint-disable no-new, @gitlab/no-runtime-template-compiler */
import { GlLabel } from '@gitlab/ui';
import $ from 'jquery';
import Vue from 'vue';
import DueDateSelectors from '~/due_date_select';
import IssuableContext from '~/issuable_context';
import LabelsSelect from '~/labels_select';
import { isScopedLabel } from '~/lib/utils/common_utils';
import { sprintf, __ } from '~/locale';
import MilestoneSelect from '~/milestone_select';
import Sidebar from '~/right_sidebar';
import AssigneeTitle from '~/sidebar/components/assignees/assignee_title.vue';
import Assignees from '~/sidebar/components/assignees/assignees.vue';
import SidebarAssigneesWidget from '~/sidebar/components/assignees/sidebar_assignees_widget.vue';
import Subscriptions from '~/sidebar/components/subscriptions/subscriptions.vue';
import TimeTracker from '~/sidebar/components/time_tracking/time_tracker.vue';
import eventHub from '~/sidebar/event_hub';
import boardsStore from '../stores/boards_store';
export default Vue.extend({
components: {
AssigneeTitle,
Assignees,
GlLabel,
SidebarEpicsSelect: () =>
import('ee_component/sidebar/components/sidebar_item_epics_select.vue'),
Subscriptions,
TimeTracker,
SidebarAssigneesWidget,
},
props: {
currentUser: {
type: Object,
default: () => ({}),
required: false,
},
},
data() {
return {
detail: boardsStore.detail,
issue: {},
list: {},
loadingAssignees: false,
timeTrackingLimitToHours: boardsStore.timeTracking.limitToHours,
};
},
computed: {
showSidebar() {
return Object.keys(this.issue).length;
},
milestoneTitle() {
return this.issue.milestone ? this.issue.milestone.title : __('No milestone');
},
canRemove() {
return !this.list?.preset;
},
hasLabels() {
return this.issue.labels && this.issue.labels.length;
},
labelDropdownTitle() {
return this.hasLabels
? sprintf(__('%{firstLabel} +%{labelCount} more'), {
firstLabel: this.issue.labels[0].title,
labelCount: this.issue.labels.length - 1,
})
: __('Label');
},
selectedLabels() {
return this.hasLabels ? this.issue.labels.map((l) => l.title).join(',') : '';
},
},
watch: {
detail: {
handler() {
if (this.issue.id !== this.detail.issue.id) {
$('.js-issue-board-sidebar', this.$el).each((i, el) => {
$(el).data('deprecatedJQueryDropdown').clearMenu();
});
}
this.issue = this.detail.issue;
this.list = this.detail.list;
},
deep: true,
},
},
created() {
eventHub.$on('sidebar.closeAll', this.closeSidebar);
},
beforeDestroy() {
eventHub.$off('sidebar.closeAll', this.closeSidebar);
},
mounted() {
new IssuableContext(this.currentUser);
new MilestoneSelect();
new DueDateSelectors();
new LabelsSelect();
new Sidebar();
},
methods: {
closeSidebar() {
this.detail.issue = {};
},
setAssignees({ assignees }) {
boardsStore.detail.issue.setAssignees(assignees);
},
showScopedLabels(label) {
return boardsStore.scopedLabels.enabled && isScopedLabel(label);
},
},
});
......@@ -6,7 +6,6 @@ import { mapActions } from 'vuex';
import 'ee_else_ce/boards/models/issue';
import 'ee_else_ce/boards/models/list';
import BoardSidebar from 'ee_else_ce/boards/components/board_sidebar';
import { setWeightFetchingState, setEpicFetchingState } from 'ee_else_ce/boards/ee_functions';
import toggleEpicsSwimlanes from 'ee_else_ce/boards/toggle_epics_swimlanes';
import toggleLabels from 'ee_else_ce/boards/toggle_labels';
......@@ -85,7 +84,6 @@ export default () => {
el: $boardApp,
components: {
BoardContent,
BoardSidebar,
BoardSettingsSidebar: () => import('~/boards/components/board_settings_sidebar.vue'),
},
provide: {
......
/* eslint-disable no-shadow, no-param-reassign,consistent-return */
/* eslint-disable no-shadow, no-param-reassign, consistent-return */
/* global List */
/* global ListIssue */
import { sortBy } from 'lodash';
import Vue from 'vue';
import BoardsStoreEE from 'ee_else_ce/boards/stores/boards_store_ee';
import { getIdFromGraphQLId } from '~/graphql_shared/utils';
import createDefaultClient from '~/lib/graphql';
......@@ -869,15 +869,4 @@ const boardsStore = {
BoardsStoreEE.initEESpecific(boardsStore);
// hacks added in order to allow milestone_select to function properly
// TODO: remove these
export function boardStoreIssueSet(...args) {
Vue.set(boardsStore.detail.issue, ...args);
}
export function boardStoreIssueDelete(...args) {
Vue.delete(boardsStore.detail.issue, ...args);
}
export default boardsStore;
/* eslint-disable max-classes-per-file */
import dateFormat from 'dateformat';
import $ from 'jquery';
import Pikaday from 'pikaday';
import initDatePicker from '~/behaviors/date_picker';
import initDeprecatedJQueryDropdown from '~/deprecated_jquery_dropdown';
import { __ } from '~/locale';
import boardsStore from './boards/stores/boards_store';
import axios from './lib/utils/axios_utils';
import { timeFor, parsePikadayDate, pikadayToString } from './lib/utils/datetime_utility';
class DueDateSelect {
constructor({ $dropdown, $loading } = {}) {
const $dropdownParent = $dropdown.closest('.dropdown');
const $block = $dropdown.closest('.block');
this.$loading = $loading;
this.$dropdown = $dropdown;
this.$dropdownParent = $dropdownParent;
this.$datePicker = $dropdownParent.find('.js-due-date-calendar');
this.$block = $block;
this.$sidebarCollapsedValue = $block.find('.sidebar-collapsed-icon');
this.$selectbox = $dropdown.closest('.selectbox');
this.$value = $block.find('.value');
this.$valueContent = $block.find('.value-content');
this.$sidebarValue = $('.js-due-date-sidebar-value', $block);
this.fieldName = $dropdown.data('fieldName');
this.abilityName = $dropdown.data('abilityName');
this.issueUpdateURL = $dropdown.data('issueUpdate');
this.rawSelectedDate = null;
this.displayedDate = null;
this.datePayload = null;
this.initGlDropdown();
this.initRemoveDueDate();
this.initDatePicker();
}
initGlDropdown() {
initDeprecatedJQueryDropdown(this.$dropdown, {
opened: () => {
const calendar = this.$datePicker.data('pikaday');
calendar.show();
},
hidden: () => {
this.$selectbox.hide();
this.$value.css('display', '');
},
shouldPropagate: false,
});
}
initDatePicker() {
const $dueDateInput = $(`input[name='${this.fieldName}']`);
const calendar = new Pikaday({
field: $dueDateInput.get(0),
theme: 'gitlab-theme',
format: 'yyyy-mm-dd',
parse: (dateString) => parsePikadayDate(dateString),
toString: (date) => pikadayToString(date),
onSelect: (dateText) => {
$dueDateInput.val(calendar.toString(dateText));
if (this.$dropdown.hasClass('js-issue-boards-due-date')) {
boardsStore.detail.issue.dueDate = $dueDateInput.val();
this.updateIssueBoardIssue();
} else {
this.saveDueDate(true);
}
},
firstDay: gon.first_day_of_week,
});
calendar.setDate(parsePikadayDate($dueDateInput.val()));
this.$datePicker.append(calendar.el);
this.$datePicker.data('pikaday', calendar);
}
initRemoveDueDate() {
this.$block.on('click', '.js-remove-due-date', (e) => {
const calendar = this.$datePicker.data('pikaday');
e.preventDefault();
calendar.setDate(null);
if (this.$dropdown.hasClass('js-issue-boards-due-date')) {
boardsStore.detail.issue.dueDate = '';
this.updateIssueBoardIssue();
} else {
$(`input[name='${this.fieldName}']`).val('');
this.saveDueDate(false);
}
});
}
saveDueDate(isDropdown) {
this.parseSelectedDate();
this.prepSelectedDate();
this.submitSelectedDate(isDropdown);
}
parseSelectedDate() {
this.rawSelectedDate = $(`input[name='${this.fieldName}']`).val();
if (this.rawSelectedDate.length) {
// Construct Date object manually to avoid buggy dateString support within Date constructor
const dateArray = this.rawSelectedDate.split('-').map((v) => parseInt(v, 10));
const dateObj = new Date(dateArray[0], dateArray[1] - 1, dateArray[2]);
this.displayedDate = dateFormat(dateObj, 'mmm d, yyyy');
} else {
this.displayedDate = __('None');
}
}
prepSelectedDate() {
const datePayload = {};
datePayload[this.abilityName] = {};
datePayload[this.abilityName].due_date = this.rawSelectedDate;
this.datePayload = datePayload;
}
updateIssueBoardIssue() {
this.$loading.removeClass('gl-display-none');
this.$dropdown.trigger('loading.gl.dropdown');
this.$selectbox.hide();
this.$value.css('display', '');
const hideLoader = () => {
this.$loading.addClass('gl-display-none');
};
boardsStore.detail.issue
.update(this.$dropdown.attr('data-issue-update'))
.then(hideLoader)
.catch(hideLoader);
}
submitSelectedDate(isDropdown) {
const selectedDateValue = this.datePayload[this.abilityName].due_date;
const hasDueDate = this.displayedDate !== __('None');
const displayedDateStyle = hasDueDate ? 'bold' : 'no-value';
this.$loading.removeClass('gl-display-none');
if (isDropdown) {
this.$dropdown.trigger('loading.gl.dropdown');
this.$selectbox.hide();
}
this.$value.css('display', '');
this.$valueContent.html(`<span class='${displayedDateStyle}'>${this.displayedDate}</span>`);
this.$sidebarValue.html(this.displayedDate);
$('.js-remove-due-date-holder').toggleClass('hidden', selectedDateValue.length);
return axios.put(this.issueUpdateURL, this.datePayload).then(() => {
const tooltipText = hasDueDate
? `${__('Due date')}<br />${selectedDateValue} (${timeFor(selectedDateValue)})`
: __('Due date');
if (isDropdown) {
this.$dropdown.trigger('loaded.gl.dropdown');
this.$dropdown.dropdown('toggle');
}
this.$sidebarCollapsedValue.attr('data-original-title', tooltipText);
return this.$loading.addClass('gl-display-none');
});
}
}
export default class DueDateSelectors {
constructor() {
initDatePicker();
this.initIssuableSelect();
}
// eslint-disable-next-line class-methods-use-this
initIssuableSelect() {
const $loading = $('.js-issuable-update .due_date')
.find('.block-loading')
.removeClass('hidden')
.addClass('gl-display-none');
$('.js-due-date-select').each((i, dropdown) => {
const $dropdown = $(dropdown);
// eslint-disable-next-line no-new
new DueDateSelect({
$dropdown,
$loading,
});
});
}
}
/* eslint-disable func-names, no-underscore-dangle, no-new, consistent-return, no-shadow, no-param-reassign, no-lonely-if, no-empty */
/* global Issuable */
/* global ListLabel */
import $ from 'jquery';
import { difference, isEqual, escape, sortBy, template, union } from 'lodash';
import initDeprecatedJQueryDropdown from '~/deprecated_jquery_dropdown';
import IssuableBulkUpdateActions from '~/issuable_bulk_update_sidebar/issuable_bulk_update_actions';
import { isScopedLabel } from '~/lib/utils/common_utils';
import boardsStore from './boards/stores/boards_store';
import CreateLabelDropdown from './create_label';
import createFlash from './flash';
import axios from './lib/utils/axios_utils';
......@@ -43,7 +41,6 @@ export default class LabelsSelect {
const $form = $dropdown.closest('form, .js-issuable-update');
const $sidebarCollapsedValue = $block.find('.sidebar-collapsed-icon span');
const $value = $block.find('.value');
const $dropdownMenu = $dropdown.parent().find('.dropdown-menu');
const $loading = $block.find('.block-loading').addClass('gl-display-none');
const fieldName = $dropdown.data('fieldName');
let initialSelected = $selectbox
......@@ -341,15 +338,11 @@ export default class LabelsSelect {
}
},
multiSelect: $dropdown.hasClass('js-multiselect'),
vue: $dropdown.hasClass('js-issue-board-sidebar'),
vue: false,
clicked(clickEvent) {
const { $el, e, isMarking } = clickEvent;
const { e, isMarking } = clickEvent;
const label = clickEvent.selectedObj;
const hideLoader = () => {
$loading.addClass('gl-display-none');
};
const page = $('body').attr('data-page');
const isIssueIndex = page === 'projects:issues:index';
const isMRIndex = page === 'projects:merge_requests:index';
......@@ -375,40 +368,6 @@ export default class LabelsSelect {
}
} else if ($dropdown.hasClass('js-filter-submit')) {
return $dropdown.closest('form').submit();
} else if ($dropdown.hasClass('js-issue-board-sidebar')) {
if ($el.hasClass('is-active')) {
boardsStore.detail.issue.labels.push(
new ListLabel({
id: label.id,
title: label.title,
color: label.color,
textColor: '#fff',
}),
);
} else {
let { labels } = boardsStore.detail.issue;
labels = labels.filter((selectedLabel) => selectedLabel.id !== label.id);
boardsStore.detail.issue.labels = labels;
}
$loading.removeClass('gl-display-none');
const oldLabels = boardsStore.detail.issue.labels;
boardsStore.detail.issue
.update($dropdown.attr('data-issue-update'))
.then(() => {
if (isScopedLabel(label)) {
const prevIds = oldLabels.map((label) => label.id);
const newIds = boardsStore.detail.issue.labels.map((label) => label.id);
const differentIds = prevIds.filter((x) => !newIds.includes(x));
$dropdown.data('marked', newIds);
$dropdownMenu
.find(differentIds.map((id) => `[data-label-id="${id}"]`).join(','))
.removeClass('is-active');
}
})
.then(hideLoader)
.catch(hideLoader);
} else if (handleClick) {
e.preventDefault();
handleClick(label);
......@@ -419,13 +378,6 @@ export default class LabelsSelect {
}
}
},
opened() {
if ($dropdown.hasClass('js-issue-board-sidebar')) {
const previousSelection = $dropdown.attr('data-selected');
this.selected = previousSelection ? previousSelection.split(',') : [];
$dropdown.data('deprecatedJQueryDropdown').updateLabel();
}
},
preserveContext: true,
});
......
/* eslint-disable one-var, no-self-compare, consistent-return, no-param-reassign, no-shadow */
/* global Issuable */
/* global ListMilestone */
import $ from 'jquery';
import { template, escape } from 'lodash';
......@@ -8,10 +7,6 @@ import Api from '~/api';
import initDeprecatedJQueryDropdown from '~/deprecated_jquery_dropdown';
import { __, sprintf } from '~/locale';
import { sortMilestonesByDueDate } from '~/milestones/milestone_utils';
import boardsStore, {
boardStoreIssueSet,
boardStoreIssueDelete,
} from './boards/stores/boards_store';
import axios from './lib/utils/axios_utils';
import { timeFor, parsePikadayDate, dateInWords } from './lib/utils/datetime_utility';
......@@ -186,18 +181,17 @@ export default class MilestoneSelect {
},
opened: (e) => {
const $el = $(e.currentTarget);
if ($dropdown.hasClass('js-issue-board-sidebar') || options.handleClick) {
if (options.handleClick) {
selectedMilestone = $dropdown[0].dataset.selected || selectedMilestoneDefault;
}
$('a.is-active', $el).removeClass('is-active');
$(`[data-milestone-id="${selectedMilestone}"] > a`, $el).addClass('is-active');
},
vue: $dropdown.hasClass('js-issue-board-sidebar'),
vue: false,
clicked: (clickEvent) => {
const { e } = clickEvent;
let selected = clickEvent.selectedObj;
let data;
if (!selected) return;
if (options.handleClick) {
......@@ -224,34 +218,11 @@ export default class MilestoneSelect {
return Issuable.filterResults($dropdown.closest('form'));
} else if ($dropdown.hasClass('js-filter-submit')) {
return $dropdown.closest('form').submit();
} else if ($dropdown.hasClass('js-issue-board-sidebar')) {
if (selected.id !== -1 && isSelecting) {
boardStoreIssueSet(
'milestone',
new ListMilestone({
id: selected.id,
title: selected.name,
}),
);
} else {
boardStoreIssueDelete('milestone');
}
$dropdown.trigger('loading.gl.dropdown');
$loading.removeClass('gl-display-none');
boardsStore.detail.issue
.update($dropdown.attr('data-issue-update'))
.then(() => {
$dropdown.trigger('loaded.gl.dropdown');
$loading.addClass('gl-display-none');
})
.catch(() => {
$loading.addClass('gl-display-none');
});
} else {
selected = $selectBox.find('input[type="hidden"]').val();
data = {};
const data = {};
data[abilityName] = {};
data[abilityName].milestone_id = selected != null ? selected : null;
$loading.removeClass('gl-display-none');
......@@ -293,7 +264,6 @@ export default class MilestoneSelect {
.catch(() => {
$loading.addClass('gl-display-none');
});
}
},
});
});
......
......@@ -536,9 +536,6 @@ function UsersSelect(currentUser, els, options = {}) {
opened(e) {
const $el = $(e.currentTarget);
const selected = getSelected();
if ($dropdown.hasClass('js-issue-board-sidebar') && selected.length === 0) {
this.addInput($dropdown.data('fieldName'), 0, {});
}
$el.find('.is-active').removeClass('is-active');
function highlightSelected(id) {
......@@ -547,8 +544,6 @@ function UsersSelect(currentUser, els, options = {}) {
if (selected.length > 0) {
getSelected().forEach((selectedId) => highlightSelected(selectedId));
} else if ($dropdown.hasClass('js-issue-board-sidebar')) {
highlightSelected(0);
} else {
highlightSelected(selectedId);
}
......
- dropdown_options = assignees_dropdown_options('issue')
- relative_url = Gitlab.config.gitlab.relative_url_root || '/'
.block.assignee{ ref: "assigneeBlock" }
%template{ "v-if" => "issue.assignees" }
%sidebar-assignees-widget{ ":iid" => "String(issue.iid)",
":full-path" => "issue.path.split('/-/')[0].substring(1).replace(`#{relative_url}`, '')",
":initial-assignees" => "issue.assignees",
":allow-multiple-assignees" => "!Boolean(#{dropdown_options[:data][:"max-select"]})",
"@assignees-updated" => "setAssignees" }
.block.due_date
.title.gl-h-5.gl-display-flex.gl-align-items-center
= _("Due date")
- if can_admin_issue?
= loading_icon(css_class: 'gl-ml-2 block-loading')
= link_to _("Edit"), "#", class: "js-sidebar-dropdown-toggle edit-link gl-ml-auto"
.value
.value-content
%span.no-value{ "v-if" => "!issue.dueDate" }
= _("None")
%span.bold{ "v-if" => "issue.dueDate" }
{{ issue.dueDate | due-date }}
- if can_admin_issue?
%span.no-value.js-remove-due-date-holder{ "v-if" => "issue.dueDate" }
\-
%a.js-remove-due-date{ href: "#", role: "button" }
= _('remove due date')
- if can_admin_issue?
.selectbox
%input{ type: "hidden",
name: "issue[due_date]",
":value" => "issue.dueDate" }
.dropdown
%button.dropdown-menu-toggle.js-due-date-select.js-issue-boards-due-date{ type: 'button',
data: { toggle: 'dropdown', field_name: "issue[due_date]", ability_name: "issue" } }
%span.dropdown-toggle-text= _("Due date")
= sprite_icon('chevron-down', css_class: "dropdown-menu-toggle-icon gl-top-3")
.dropdown-menu.dropdown-menu-due-date
= dropdown_title(_('Due date'))
= dropdown_content do
.js-due-date-calendar
.block.labels
.title.gl-h-5.gl-display-flex.gl-align-items-center
= _("Labels")
- if can_admin_issue?
= loading_icon(css_class: 'gl-ml-2 block-loading')
= link_to _("Edit"), "#", class: "js-sidebar-dropdown-toggle edit-link gl-ml-auto"
.value.issuable-show-labels.dont-hide
%span.no-value{ "v-if" => "issue.labels && issue.labels.length === 0" }
= _("None")
%span{ "v-for" => "label in issue.labels" }
%gl-label{ ":key" => "label.id",
":background-color" => "label.color",
":title" => "label.title",
":description" => "label.description",
":scoped" => "showScopedLabels(label)" }
- if can_admin_issue?
.selectbox
%input{ type: "hidden",
name: "issue[label_names][]",
"v-for" => "label in issue.labels",
":value" => "label.id" }
.dropdown
%button.dropdown-menu-toggle.js-label-select.js-multiselect.js-issue-board-sidebar{ type: "button",
":data-selected" => "selectedLabels",
":data-labels" => "issue.assignableLabelsEndpoint",
data: label_dropdown_data(@project, namespace_path: @namespace_path, field_name: "issue[label_names][]") }
%span.dropdown-toggle-text
{{ labelDropdownTitle }}
= sprite_icon('chevron-down', css_class: "dropdown-menu-toggle-icon gl-top-3")
.dropdown-menu.dropdown-select.dropdown-menu-paging.dropdown-menu-labels.dropdown-menu-selectable.dropdown-extended-height
= render partial: "shared/issuable/label_page_default"
- if can?(current_user, :admin_label, current_board_parent)
= render partial: "shared/issuable/label_page_create", locals: { show_add_list: true }
.block.milestone
.title.gl-h-5.gl-display-flex.gl-align-items-center
= _("Milestone")
- if can_admin_issue?
= loading_icon(css_class: 'gl-ml-2 block-loading')
= link_to _("Edit"), "#", class: "js-sidebar-dropdown-toggle edit-link gl-ml-auto"
.value
%span.no-value{ "v-if" => "!issue.milestone" }
= _("None")
%span.bold.has-tooltip{ "v-if" => "issue.milestone" }
{{ issue.milestone.title }}
- if can_admin_issue?
.selectbox
%input{ type: "hidden",
":value" => "issue.milestone.id",
name: "issue[milestone_id]",
"v-if" => "issue.milestone" }
.dropdown
%button.dropdown-menu-toggle.js-milestone-select.js-issue-board-sidebar{ type: "button", data: { toggle: "dropdown", show_no: "true", field_name: "issue[milestone_id]", ability_name: "issue", use_id: "true", default_no: "true" },
":data-selected" => "milestoneTitle",
":data-issuable-id" => "issue.iid",
":data-project-id" => "issue.project_id" }
= _("Milestone")
= sprite_icon('chevron-down', css_class: "dropdown-menu-toggle-icon gl-top-3")
.dropdown-menu.dropdown-select.dropdown-menu-selectable
= dropdown_title(_("Assign milestone"))
= dropdown_filter(_("Search milestones"))
= dropdown_content
= dropdown_loading
- if current_user
.block.subscriptions
%subscriptions{ ":loading" => "issue.isFetching && issue.isFetching.subscriptions",
":subscribed" => "issue.subscribed",
":id" => "issue.id" }
.block.time-tracking
%time-tracker{ ":limit-to-hours" => "timeTrackingLimitToHours",
":issuable-id" => "issue.id ? issue.id.toString() : ''",
":issuable-iid" => "issue.iid ? issue.iid.toString() : ''",
":full-path" => "issue.project ? issue.project.fullPath : ''",
"root-path" => "#{root_url}" }
import Weight from 'ee/sidebar/components/weight/weight.vue';
import BoardSidebar from '~/boards/components/board_sidebar';
export default BoardSidebar.extend({
components: {
Weight,
},
});
<script>
import EpicsSelect from 'ee/vue_shared/components/sidebar/epics_select/base.vue';
import { noneEpic } from 'ee/vue_shared/constants';
import { convertObjectPropsToCamelCase } from '~/lib/utils/common_utils';
export default {
components: {
EpicsSelect,
},
props: {
canEdit: {
type: Boolean,
required: true,
},
sidebarStore: {
type: Object,
required: true,
},
groupId: {
type: Number,
required: true,
},
issueId: {
type: Number,
required: false,
default: 0,
},
epicIssueId: {
type: Number,
required: true,
default: 0,
},
initialEpic: {
type: Object,
required: false,
default: () => null,
},
},
data() {
return {
initialEpicLoading: this.getInitialEpicLoading(),
epic: this.getEpic(),
};
},
watch: {
/**
* sidebarStore is updated async while in Issue Boards
* hence we need a _deep watch_ to update `initialEpicLoading`
* and `epic` props.
*/
sidebarStore: {
handler() {
this.initialEpicLoading = this.getInitialEpicLoading();
this.epic = convertObjectPropsToCamelCase(this.getEpic());
},
deep: true,
},
},
methods: {
getInitialEpicLoading() {
if (this.initialEpic) {
return false;
} else if (this.sidebarStore.isFetching) {
// We need to cast `epic` into boolean as when
// new issue is created from board, `isFetching`
// does not contain `epic` within it.
return Boolean(this.sidebarStore.isFetching.epic);
}
return false;
},
getEpic() {
if (this.initialEpic) {
return this.initialEpic;
} else if (this.sidebarStore.epic && this.sidebarStore.epic.id) {
return this.sidebarStore.epic;
}
return noneEpic;
},
},
};
</script>
<template>
<epics-select
:group-id="groupId"
:issue-id="issueId"
:epic-issue-id="epicIssueId"
:can-edit="canEdit"
:initial-epic="epic"
:initial-epic-loading="initialEpicLoading"
>
{{ __('None') }}
</epics-select>
</template>
- return unless @group&.feature_available?(:epics) || @project&.group&.feature_available?(:epics)
%sidebar-epics-select{ ":sidebar-store" => "issue",
":group-id": "#{@project&.group&.id || @group&.id}",
":issue-id": "issue.id",
":epic-issue-id": "(issue.epic && issue.epic.epic_issue_id) || 0",
":can-edit": can_admin_issue? }
- if (@project || @group)&.feature_available?(:issue_weights)
%weight{ ":fetching" => "issue.isFetching && issue.isFetching.weight",
":loading" => "issue.isLoading && issue.isLoading.weight",
":weight" => "issue.weight",
":weight-options" => Issue.weight_options,
"weight-none-value" => Issue::WEIGHT_NONE,
":editable" => can_admin_issue?,
":id" => "issue.id" }
import { shallowMount } from '@vue/test-utils';
import SidebarItemEpicsSelect from 'ee/sidebar/components/sidebar_item_epics_select.vue';
import EpicsSelect from 'ee/vue_shared/components/sidebar/epics_select/base.vue';
import {
mockSidebarStore,
mockEpic1,
mockIssue,
} from 'ee_jest/vue_shared/components/sidebar/mock_data';
describe('SidebarItemEpicsSelect', () => {
let wrapper;
beforeEach(() => {
wrapper = shallowMount(SidebarItemEpicsSelect, {
stubs: {
'epics-select': true,
},
propsData: {
canEdit: true,
sidebarStore: mockSidebarStore,
epicIssueId: mockSidebarStore.epic_issue_id,
groupId: mockEpic1.group_id,
issueId: mockIssue.id,
},
});
});
afterEach(() => {
wrapper.destroy();
wrapper = null;
});
describe('methods', () => {
describe('getInitialEpicLoading', () => {
it('should return `false` when `initialEpic` prop is provided', async () => {
wrapper.setProps({
initialEpic: mockEpic1,
});
await wrapper.vm.$nextTick();
expect(wrapper.vm.getInitialEpicLoading()).toBe(false);
});
it('should return value of `sidebarStore.isFetching.epic` when `initialEpic` prop is null and `isFetching` is available', async () => {
wrapper.setProps({
sidebarStore: { isFetching: { epic: true } },
});
await wrapper.vm.$nextTick();
expect(wrapper.vm.getInitialEpicLoading()).toBe(true);
});
it('should return `false` when both `initialEpic` and `sidebarStore.isFetching` are unavailable', async () => {
wrapper.setProps({
initialEpic: null,
sidebarStore: { isFetching: null },
});
await wrapper.vm.$nextTick();
expect(wrapper.vm.getInitialEpicLoading()).toBe(false);
});
});
describe('getEpic', () => {
it('should return value of `initialEpic` as it is when it is available', async () => {
wrapper.setProps({
initialEpic: mockEpic1,
});
await wrapper.vm.$nextTick();
expect(wrapper.vm.getEpic()).toBe(mockEpic1);
});
it('should return value of `sidebarStore.epic` as it is when it is available', () => {
expect(wrapper.vm.getEpic()).toBe(mockEpic1);
});
it('should return No Epic object as it is when both `initialEpic` & `sidebarStore.epic` are unavailable', async () => {
wrapper.setProps({
initialEpic: null,
sidebarStore: { epic: null },
});
await wrapper.vm.$nextTick();
expect(wrapper.vm.getEpic()).toEqual(
expect.objectContaining({
id: 0,
title: 'No Epic',
}),
);
});
});
});
describe('template', () => {
it('should render epics-select component', () => {
expect(wrapper.find(EpicsSelect).element).toBe(wrapper.element);
expect(wrapper.text()).toBe('None');
});
});
});
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