1<script>
2import { GlDrawer } from '@gitlab/ui';
3import { MountingPortal } from 'portal-vue';
4import { mapState, mapActions, mapGetters } from 'vuex';
5import SidebarDropdownWidget from 'ee_else_ce/sidebar/components/sidebar_dropdown_widget.vue';
6import { __, sprintf } from '~/locale';
7import BoardSidebarTimeTracker from '~/boards/components/sidebar/board_sidebar_time_tracker.vue';
8import BoardSidebarTitle from '~/boards/components/sidebar/board_sidebar_title.vue';
9import { ISSUABLE } from '~/boards/constants';
10import { getIdFromGraphQLId } from '~/graphql_shared/utils';
11import SidebarAssigneesWidget from '~/sidebar/components/assignees/sidebar_assignees_widget.vue';
12import SidebarConfidentialityWidget from '~/sidebar/components/confidential/sidebar_confidentiality_widget.vue';
13import SidebarDateWidget from '~/sidebar/components/date/sidebar_date_widget.vue';
14import SidebarSubscriptionsWidget from '~/sidebar/components/subscriptions/sidebar_subscriptions_widget.vue';
15import SidebarTodoWidget from '~/sidebar/components/todo_toggle/sidebar_todo_widget.vue';
16import SidebarLabelsWidget from '~/vue_shared/components/sidebar/labels_select_widget/labels_select_root.vue';
17import { LabelType } from '~/vue_shared/components/sidebar/labels_select_widget/constants';
18import glFeatureFlagMixin from '~/vue_shared/mixins/gl_feature_flags_mixin';
19
20export default {
21  components: {
22    GlDrawer,
23    BoardSidebarTitle,
24    SidebarAssigneesWidget,
25    SidebarDateWidget,
26    SidebarConfidentialityWidget,
27    BoardSidebarTimeTracker,
28    SidebarLabelsWidget,
29    SidebarSubscriptionsWidget,
30    SidebarDropdownWidget,
31    SidebarTodoWidget,
32    MountingPortal,
33    SidebarWeightWidget: () =>
34      import('ee_component/sidebar/components/weight/sidebar_weight_widget.vue'),
35    IterationSidebarDropdownWidget: () =>
36      import('ee_component/sidebar/components/iteration_sidebar_dropdown_widget.vue'),
37  },
38  mixins: [glFeatureFlagMixin()],
39  inject: {
40    multipleAssigneesFeatureAvailable: {
41      default: false,
42    },
43    epicFeatureAvailable: {
44      default: false,
45    },
46    iterationFeatureAvailable: {
47      default: false,
48    },
49    weightFeatureAvailable: {
50      default: false,
51    },
52    allowLabelEdit: {
53      default: false,
54    },
55    labelsFilterBasePath: {
56      default: '',
57    },
58  },
59  inheritAttrs: false,
60  computed: {
61    ...mapGetters([
62      'isGroupBoard',
63      'isSidebarOpen',
64      'activeBoardItem',
65      'groupPathForActiveIssue',
66      'projectPathForActiveIssue',
67    ]),
68    ...mapState(['sidebarType', 'issuableType']),
69    isIssuableSidebar() {
70      return this.sidebarType === ISSUABLE;
71    },
72    showSidebar() {
73      return this.isIssuableSidebar && this.isSidebarOpen;
74    },
75    fullPath() {
76      return this.activeBoardItem?.referencePath?.split('#')[0] || '';
77    },
78    createLabelTitle() {
79      return sprintf(__('Create %{workspace} label'), {
80        workspace: this.isGroupBoard ? 'group' : 'project',
81      });
82    },
83    manageLabelTitle() {
84      return sprintf(__('Manage %{workspace} labels'), {
85        workspace: this.isGroupBoard ? 'group' : 'project',
86      });
87    },
88    attrWorkspacePath() {
89      return this.isGroupBoard ? this.groupPathForActiveIssue : this.projectPathForActiveIssue;
90    },
91    labelType() {
92      return this.isGroupBoard ? LabelType.group : LabelType.project;
93    },
94    labelsFilterPath() {
95      return this.isGroupBoard
96        ? this.labelsFilterBasePath.replace(':project_path', this.projectPathForActiveIssue)
97        : this.labelsFilterBasePath;
98    },
99  },
100  methods: {
101    ...mapActions([
102      'toggleBoardItem',
103      'setAssignees',
104      'setActiveItemConfidential',
105      'setActiveBoardItemLabels',
106      'setActiveItemWeight',
107    ]),
108    handleClose() {
109      this.toggleBoardItem({ boardItem: this.activeBoardItem, sidebarType: this.sidebarType });
110    },
111    handleUpdateSelectedLabels({ labels, id }) {
112      this.setActiveBoardItemLabels({
113        id,
114        projectPath: this.projectPathForActiveIssue,
115        labelIds: labels.map((label) => getIdFromGraphQLId(label.id)),
116        labels,
117      });
118    },
119    handleLabelRemove(removeLabelId) {
120      this.setActiveBoardItemLabels({
121        iid: this.activeBoardItem.iid,
122        projectPath: this.projectPathForActiveIssue,
123        removeLabelIds: [removeLabelId],
124      });
125    },
126  },
127};
128</script>
129
130<template>
131  <mounting-portal mount-to="#js-right-sidebar-portal" name="board-content-sidebar" append>
132    <gl-drawer
133      v-if="showSidebar"
134      v-bind="$attrs"
135      :open="isSidebarOpen"
136      class="boards-sidebar gl-absolute"
137      variant="sidebar"
138      @close="handleClose"
139    >
140      <template #title>
141        <h2 class="gl-my-0 gl-font-size-h2 gl-line-height-24">{{ __('Issue details') }}</h2>
142      </template>
143      <template #header>
144        <sidebar-todo-widget
145          class="gl-mt-3"
146          :issuable-id="activeBoardItem.id"
147          :issuable-iid="activeBoardItem.iid"
148          :full-path="fullPath"
149          :issuable-type="issuableType"
150        />
151      </template>
152      <template #default>
153        <board-sidebar-title />
154        <sidebar-assignees-widget
155          :iid="activeBoardItem.iid"
156          :full-path="fullPath"
157          :initial-assignees="activeBoardItem.assignees"
158          :allow-multiple-assignees="multipleAssigneesFeatureAvailable"
159          @assignees-updated="setAssignees"
160        />
161        <sidebar-dropdown-widget
162          v-if="epicFeatureAvailable"
163          :iid="activeBoardItem.iid"
164          issuable-attribute="epic"
165          :workspace-path="projectPathForActiveIssue"
166          :attr-workspace-path="groupPathForActiveIssue"
167          :issuable-type="issuableType"
168          data-testid="sidebar-epic"
169        />
170        <div>
171          <sidebar-dropdown-widget
172            :iid="activeBoardItem.iid"
173            issuable-attribute="milestone"
174            :workspace-path="projectPathForActiveIssue"
175            :attr-workspace-path="projectPathForActiveIssue"
176            :issuable-type="issuableType"
177            data-testid="sidebar-milestones"
178          />
179          <template v-if="!glFeatures.iterationCadences">
180            <sidebar-dropdown-widget
181              v-if="iterationFeatureAvailable"
182              :iid="activeBoardItem.iid"
183              issuable-attribute="iteration"
184              :workspace-path="projectPathForActiveIssue"
185              :attr-workspace-path="groupPathForActiveIssue"
186              :issuable-type="issuableType"
187              class="gl-mt-5"
188              data-testid="iteration-edit"
189            />
190          </template>
191          <template v-else>
192            <iteration-sidebar-dropdown-widget
193              v-if="iterationFeatureAvailable"
194              :iid="activeBoardItem.iid"
195              :workspace-path="projectPathForActiveIssue"
196              :attr-workspace-path="groupPathForActiveIssue"
197              :issuable-type="issuableType"
198              class="gl-mt-5"
199              data-testid="iteration-edit"
200            />
201          </template>
202        </div>
203        <board-sidebar-time-tracker class="swimlanes-sidebar-time-tracker" />
204        <sidebar-date-widget
205          :iid="activeBoardItem.iid"
206          :full-path="fullPath"
207          :issuable-type="issuableType"
208          data-testid="sidebar-due-date"
209        />
210        <sidebar-labels-widget
211          class="block labels"
212          data-testid="sidebar-labels"
213          :iid="activeBoardItem.iid"
214          :full-path="projectPathForActiveIssue"
215          :allow-label-remove="allowLabelEdit"
216          :allow-multiselect="true"
217          :footer-create-label-title="createLabelTitle"
218          :footer-manage-label-title="manageLabelTitle"
219          :labels-create-title="createLabelTitle"
220          :labels-filter-base-path="labelsFilterPath"
221          :attr-workspace-path="attrWorkspacePath"
222          workspace-type="project"
223          :issuable-type="issuableType"
224          :label-create-type="labelType"
225          @onLabelRemove="handleLabelRemove"
226          @updateSelectedLabels="handleUpdateSelectedLabels"
227        >
228          {{ __('None') }}
229        </sidebar-labels-widget>
230        <sidebar-weight-widget
231          v-if="weightFeatureAvailable"
232          :iid="activeBoardItem.iid"
233          :full-path="fullPath"
234          :issuable-type="issuableType"
235          @weightUpdated="setActiveItemWeight($event)"
236        />
237        <sidebar-confidentiality-widget
238          :iid="activeBoardItem.iid"
239          :full-path="fullPath"
240          :issuable-type="issuableType"
241          @confidentialityUpdated="setActiveItemConfidential($event)"
242        />
243        <sidebar-subscriptions-widget
244          :iid="activeBoardItem.iid"
245          :full-path="fullPath"
246          :issuable-type="issuableType"
247          data-testid="sidebar-notifications"
248        />
249      </template>
250    </gl-drawer>
251  </mounting-portal>
252</template>
253