summaryrefslogtreecommitdiff
path: root/app/assets/javascripts/sidebar/components
diff options
context:
space:
mode:
authorGitLab Bot <gitlab-bot@gitlab.com>2020-05-20 14:34:42 +0000
committerGitLab Bot <gitlab-bot@gitlab.com>2020-05-20 14:34:42 +0000
commit9f46488805e86b1bc341ea1620b866016c2ce5ed (patch)
treef9748c7e287041e37d6da49e0a29c9511dc34768 /app/assets/javascripts/sidebar/components
parentdfc92d081ea0332d69c8aca2f0e745cb48ae5e6d (diff)
downloadgitlab-ce-9f46488805e86b1bc341ea1620b866016c2ce5ed.tar.gz
Add latest changes from gitlab-org/gitlab@13-0-stable-ee
Diffstat (limited to 'app/assets/javascripts/sidebar/components')
-rw-r--r--app/assets/javascripts/sidebar/components/assignees/assignees.vue4
-rw-r--r--app/assets/javascripts/sidebar/components/assignees/assignees_realtime.vue75
-rw-r--r--app/assets/javascripts/sidebar/components/assignees/sidebar_assignees.vue24
-rw-r--r--app/assets/javascripts/sidebar/components/assignees/uncollapsed_assignee_list.vue2
-rw-r--r--app/assets/javascripts/sidebar/components/confidential/confidential_issue_sidebar.vue23
-rw-r--r--app/assets/javascripts/sidebar/components/confidential/edit_form_buttons.vue7
-rw-r--r--app/assets/javascripts/sidebar/components/participants/participants.vue18
7 files changed, 123 insertions, 30 deletions
diff --git a/app/assets/javascripts/sidebar/components/assignees/assignees.vue b/app/assets/javascripts/sidebar/components/assignees/assignees.vue
index f16b16a6837..3baf4bf0742 100644
--- a/app/assets/javascripts/sidebar/components/assignees/assignees.vue
+++ b/app/assets/javascripts/sidebar/components/assignees/assignees.vue
@@ -1,6 +1,6 @@
<script>
-import CollapsedAssigneeList from '../assignees/collapsed_assignee_list.vue';
-import UncollapsedAssigneeList from '../assignees/uncollapsed_assignee_list.vue';
+import CollapsedAssigneeList from './collapsed_assignee_list.vue';
+import UncollapsedAssigneeList from './uncollapsed_assignee_list.vue';
export default {
// name: 'Assignees' is a false positive: https://gitlab.com/gitlab-org/frontend/eslint-plugin-i18n/issues/26#possible-false-positives
diff --git a/app/assets/javascripts/sidebar/components/assignees/assignees_realtime.vue b/app/assets/javascripts/sidebar/components/assignees/assignees_realtime.vue
new file mode 100644
index 00000000000..bf0c52b2341
--- /dev/null
+++ b/app/assets/javascripts/sidebar/components/assignees/assignees_realtime.vue
@@ -0,0 +1,75 @@
+<script>
+import { getIdFromGraphQLId } from '~/graphql_shared/utils';
+import query from '~/issuable_sidebar/queries/issue_sidebar.query.graphql';
+import actionCable from '~/actioncable_consumer';
+
+export default {
+ subscription: null,
+ name: 'AssigneesRealtime',
+ props: {
+ mediator: {
+ type: Object,
+ required: true,
+ },
+ issuableIid: {
+ type: String,
+ required: true,
+ },
+ projectPath: {
+ type: String,
+ required: true,
+ },
+ },
+ apollo: {
+ project: {
+ query,
+ variables() {
+ return {
+ iid: this.issuableIid,
+ fullPath: this.projectPath,
+ };
+ },
+ result(data) {
+ this.handleFetchResult(data);
+ },
+ },
+ },
+ mounted() {
+ this.initActionCablePolling();
+ },
+ beforeDestroy() {
+ this.$options.subscription.unsubscribe();
+ },
+ methods: {
+ received(data) {
+ if (data.event === 'updated') {
+ this.$apollo.queries.project.refetch();
+ }
+ },
+ initActionCablePolling() {
+ this.$options.subscription = actionCable.subscriptions.create(
+ {
+ channel: 'IssuesChannel',
+ project_path: this.projectPath,
+ iid: this.issuableIid,
+ },
+ { received: this.received },
+ );
+ },
+ handleFetchResult({ data }) {
+ const { nodes } = data.project.issue.assignees;
+
+ const assignees = nodes.map(n => ({
+ ...n,
+ avatar_url: n.avatarUrl,
+ id: getIdFromGraphQLId(n.id),
+ }));
+
+ this.mediator.store.setAssigneesFromRealtime(assignees);
+ },
+ },
+ render() {
+ return this.$slots.default;
+ },
+};
+</script>
diff --git a/app/assets/javascripts/sidebar/components/assignees/sidebar_assignees.vue b/app/assets/javascripts/sidebar/components/assignees/sidebar_assignees.vue
index ce592720531..0906d5abec3 100644
--- a/app/assets/javascripts/sidebar/components/assignees/sidebar_assignees.vue
+++ b/app/assets/javascripts/sidebar/components/assignees/sidebar_assignees.vue
@@ -3,8 +3,10 @@ import Flash from '~/flash';
import eventHub from '~/sidebar/event_hub';
import Store from '~/sidebar/stores/sidebar_store';
import { refreshUserMergeRequestCounts } from '~/commons/nav/user_merge_requests';
+import glFeatureFlagsMixin from '~/vue_shared/mixins/gl_feature_flags_mixin';
import AssigneeTitle from './assignee_title.vue';
import Assignees from './assignees.vue';
+import AssigneesRealtime from './assignees_realtime.vue';
import { __ } from '~/locale';
export default {
@@ -12,7 +14,9 @@ export default {
components: {
AssigneeTitle,
Assignees,
+ AssigneesRealtime,
},
+ mixins: [glFeatureFlagsMixin()],
props: {
mediator: {
type: Object,
@@ -32,6 +36,14 @@ export default {
required: false,
default: 'issue',
},
+ issuableIid: {
+ type: String,
+ required: true,
+ },
+ projectPath: {
+ type: String,
+ required: true,
+ },
},
data() {
return {
@@ -39,6 +51,12 @@ export default {
loading: false,
};
},
+ computed: {
+ shouldEnableRealtime() {
+ // Note: Realtime is only available on issues right now, future support for MR wil be built later.
+ return this.glFeatures.realTimeIssueSidebar && this.issuableType === 'issue';
+ },
+ },
created() {
this.removeAssignee = this.store.removeAssignee.bind(this.store);
this.addAssignee = this.store.addAssignee.bind(this.store);
@@ -84,6 +102,12 @@ export default {
<template>
<div>
+ <assignees-realtime
+ v-if="shouldEnableRealtime"
+ :issuable-iid="issuableIid"
+ :project-path="projectPath"
+ :mediator="mediator"
+ />
<assignee-title
:number-of-assignees="store.assignees.length"
:loading="loading || store.isFetching.assignees"
diff --git a/app/assets/javascripts/sidebar/components/assignees/uncollapsed_assignee_list.vue b/app/assets/javascripts/sidebar/components/assignees/uncollapsed_assignee_list.vue
index 3d112bba668..fed9e5886c0 100644
--- a/app/assets/javascripts/sidebar/components/assignees/uncollapsed_assignee_list.vue
+++ b/app/assets/javascripts/sidebar/components/assignees/uncollapsed_assignee_list.vue
@@ -66,7 +66,7 @@ export default {
<template>
<assignee-avatar-link
v-if="hasOneUser"
- v-slot="{ user }"
+ #default="{ user }"
tooltip-placement="left"
:tooltip-has-name="false"
:user="firstUser"
diff --git a/app/assets/javascripts/sidebar/components/confidential/confidential_issue_sidebar.vue b/app/assets/javascripts/sidebar/components/confidential/confidential_issue_sidebar.vue
index 5b3c3642290..550a1be1e64 100644
--- a/app/assets/javascripts/sidebar/components/confidential/confidential_issue_sidebar.vue
+++ b/app/assets/javascripts/sidebar/components/confidential/confidential_issue_sidebar.vue
@@ -1,15 +1,16 @@
<script>
+import { mapState } from 'vuex';
import { __ } from '~/locale';
import Flash from '~/flash';
import tooltip from '~/vue_shared/directives/tooltip';
import Icon from '~/vue_shared/components/icon.vue';
import eventHub from '~/sidebar/event_hub';
-import editForm from './edit_form.vue';
+import EditForm from './edit_form.vue';
import recaptchaModalImplementor from '~/vue_shared/mixins/recaptcha_modal_implementor';
export default {
components: {
- editForm,
+ EditForm,
Icon,
},
directives: {
@@ -17,10 +18,6 @@ export default {
},
mixins: [recaptchaModalImplementor],
props: {
- isConfidential: {
- required: true,
- type: Boolean,
- },
isEditable: {
required: true,
type: Boolean,
@@ -36,11 +33,12 @@ export default {
};
},
computed: {
+ ...mapState({ confidential: ({ noteableData }) => noteableData.confidential }),
confidentialityIcon() {
- return this.isConfidential ? 'eye-slash' : 'eye';
+ return this.confidential ? 'eye-slash' : 'eye';
},
tooltipLabel() {
- return this.isConfidential ? __('Confidential') : __('Not confidential');
+ return this.confidential ? __('Confidential') : __('Not confidential');
},
},
created() {
@@ -95,17 +93,16 @@ export default {
data-track-label="right_sidebar"
data-track-property="confidentiality"
@click.prevent="toggleForm"
+ >{{ __('Edit') }}</a
>
- {{ __('Edit') }}
- </a>
</div>
<div class="value sidebar-item-value hide-collapsed">
- <editForm
+ <edit-form
v-if="edit"
- :is-confidential="isConfidential"
+ :is-confidential="confidential"
:update-confidential-attribute="updateConfidentialAttribute"
/>
- <div v-if="!isConfidential" class="no-value sidebar-item-value">
+ <div v-if="!confidential" class="no-value sidebar-item-value">
<icon :size="16" name="eye" aria-hidden="true" class="sidebar-item-icon inline" />
{{ __('Not confidential') }}
</div>
diff --git a/app/assets/javascripts/sidebar/components/confidential/edit_form_buttons.vue b/app/assets/javascripts/sidebar/components/confidential/edit_form_buttons.vue
index 5d0e39e8195..e106afea9f5 100644
--- a/app/assets/javascripts/sidebar/components/confidential/edit_form_buttons.vue
+++ b/app/assets/javascripts/sidebar/components/confidential/edit_form_buttons.vue
@@ -40,7 +40,12 @@ export default {
<button type="button" class="btn btn-default append-right-10" @click="closeForm">
{{ __('Cancel') }}
</button>
- <button type="button" class="btn btn-close" @click.prevent="submitForm">
+ <button
+ type="button"
+ class="btn btn-close"
+ data-testid="confidential-toggle"
+ @click.prevent="submitForm"
+ >
{{ toggleButtonText }}
</button>
</div>
diff --git a/app/assets/javascripts/sidebar/components/participants/participants.vue b/app/assets/javascripts/sidebar/components/participants/participants.vue
index db2e51c3aca..d2904f4157c 100644
--- a/app/assets/javascripts/sidebar/components/participants/participants.vue
+++ b/app/assets/javascripts/sidebar/components/participants/participants.vue
@@ -95,22 +95,18 @@ export default {
@click="onClickCollapsedIcon"
>
<i class="fa fa-users" aria-hidden="true"> </i>
- <gl-loading-icon v-if="loading" class="js-participants-collapsed-loading-icon" />
- <span v-else class="js-participants-collapsed-count"> {{ participantCount }} </span>
+ <gl-loading-icon v-if="loading" />
+ <span v-else data-testid="collapsed-count"> {{ participantCount }} </span>
</div>
<div v-if="showParticipantLabel" class="title hide-collapsed">
- <gl-loading-icon
- v-if="loading"
- :inline="true"
- class="js-participants-expanded-loading-icon"
- />
+ <gl-loading-icon v-if="loading" :inline="true" />
{{ participantLabel }}
</div>
<div class="participants-list hide-collapsed">
<div
v-for="participant in visibleParticipants"
:key="participant.id"
- class="participants-author js-participants-author"
+ class="participants-author"
>
<a :href="participant.web_url" class="author-link">
<user-avatar-image
@@ -125,11 +121,7 @@ export default {
</div>
</div>
<div v-if="hasMoreParticipants" class="participants-more hide-collapsed">
- <button
- type="button"
- class="btn-transparent btn-link js-toggle-participants-button"
- @click="toggleMoreParticipants"
- >
+ <button type="button" class="btn-transparent btn-link" @click="toggleMoreParticipants">
{{ toggleLabel }}
</button>
</div>