diff options
author | GitLab Bot <gitlab-bot@gitlab.com> | 2020-05-20 14:34:42 +0000 |
---|---|---|
committer | GitLab Bot <gitlab-bot@gitlab.com> | 2020-05-20 14:34:42 +0000 |
commit | 9f46488805e86b1bc341ea1620b866016c2ce5ed (patch) | |
tree | f9748c7e287041e37d6da49e0a29c9511dc34768 /app/assets/javascripts/sidebar/components | |
parent | dfc92d081ea0332d69c8aca2f0e745cb48ae5e6d (diff) | |
download | gitlab-ce-9f46488805e86b1bc341ea1620b866016c2ce5ed.tar.gz |
Add latest changes from gitlab-org/gitlab@13-0-stable-ee
Diffstat (limited to 'app/assets/javascripts/sidebar/components')
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> |