Welcome to mirror list, hosted at ThFree Co, Russian Federation.

gitlab.com/gitlab-org/gitlab-foss.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorGitLab Bot <gitlab-bot@gitlab.com>2023-07-12 15:11:02 +0300
committerGitLab Bot <gitlab-bot@gitlab.com>2023-07-12 15:11:02 +0300
commit3d6dddf134ebb82f2a9894cad738c84ff9d6e723 (patch)
tree64e9b716ec79c086c10ef88f36daac05abb75437 /app/assets/javascripts/design_management
parent447c1bba679be70f9c311326ca03923c6988f127 (diff)
Add latest changes from gitlab-org/gitlab@master
Diffstat (limited to 'app/assets/javascripts/design_management')
-rw-r--r--app/assets/javascripts/design_management/components/design_notes/design_discussion.vue2
-rw-r--r--app/assets/javascripts/design_management/components/design_notes/design_note.vue158
-rw-r--r--app/assets/javascripts/design_management/components/design_notes/design_note_awards_list.vue34
-rw-r--r--app/assets/javascripts/design_management/graphql/fragments/design_note.fragment.graphql9
-rw-r--r--app/assets/javascripts/design_management/graphql/fragments/note_permissions.fragment.graphql1
-rw-r--r--app/assets/javascripts/design_management/graphql/mutations/design_note_award_emoji_toggle.mutation.graphql6
6 files changed, 207 insertions, 3 deletions
diff --git a/app/assets/javascripts/design_management/components/design_notes/design_discussion.vue b/app/assets/javascripts/design_management/components/design_notes/design_discussion.vue
index a890d2ba933..45f33967476 100644
--- a/app/assets/javascripts/design_management/components/design_notes/design_discussion.vue
+++ b/app/assets/javascripts/design_management/components/design_notes/design_discussion.vue
@@ -302,6 +302,7 @@ export default {
:is-resolving="isResolving"
:is-discussion="true"
:noteable-id="noteableId"
+ :design-variables="designVariables"
@delete-note="showDeleteNoteConfirmationModal($event)"
>
<template v-if="isLoggedIn && discussion.resolvable" #resolve-discussion>
@@ -344,6 +345,7 @@ export default {
:is-resolving="isResolving"
:noteable-id="noteableId"
:is-discussion="false"
+ :design-variables="designVariables"
@delete-note="showDeleteNoteConfirmationModal($event)"
/>
<li
diff --git a/app/assets/javascripts/design_management/components/design_notes/design_note.vue b/app/assets/javascripts/design_management/components/design_notes/design_note.vue
index ff7af7ef69f..d4982e39525 100644
--- a/app/assets/javascripts/design_management/components/design_notes/design_note.vue
+++ b/app/assets/javascripts/design_management/components/design_notes/design_note.vue
@@ -5,16 +5,24 @@ import {
GlButton,
GlDisclosureDropdown,
GlLink,
+ GlIcon,
GlTooltipDirective,
} from '@gitlab/ui';
+import * as Sentry from '@sentry/browser';
+import { produce } from 'immer';
import SafeHtml from '~/vue_shared/directives/safe_html';
-import { getIdFromGraphQLId } from '~/graphql_shared/utils';
+import { getIdFromGraphQLId, convertToGraphQLId } from '~/graphql_shared/utils';
+import { TYPENAME_USER } from '~/graphql_shared/constants';
import { __ } from '~/locale';
import TimelineEntryItem from '~/vue_shared/components/notes/timeline_entry_item.vue';
import TimeAgoTooltip from '~/vue_shared/components/time_ago_tooltip.vue';
+import EmojiPicker from '~/emoji/components/picker.vue';
+import getDesignQuery from '../../graphql/queries/get_design.query.graphql';
import updateNoteMutation from '../../graphql/mutations/update_note.mutation.graphql';
+import designNoteAwardEmojiToggleMutation from '../../graphql/mutations/design_note_award_emoji_toggle.mutation.graphql';
import { hasErrors } from '../../utils/cache_update';
import { findNoteId, extractDesignNoteId } from '../../utils/design_management_utils';
+import DesignNoteAwardsList from './design_note_awards_list.vue';
import DesignReplyForm from './design_reply_form.vue';
export default {
@@ -24,7 +32,10 @@ export default {
deleteCommentText: __('Delete comment'),
},
components: {
+ EmojiPicker,
+ DesignNoteAwardsList,
DesignReplyForm,
+ GlIcon,
GlAvatar,
GlAvatarLink,
GlButton,
@@ -37,6 +48,7 @@ export default {
GlTooltip: GlTooltipDirective,
SafeHtml,
},
+ inject: ['issueIid', 'projectPath'],
props: {
note: {
type: Object,
@@ -56,6 +68,10 @@ export default {
type: String,
required: true,
},
+ designVariables: {
+ type: Object,
+ required: true,
+ },
},
data() {
return {
@@ -64,6 +80,26 @@ export default {
};
},
computed: {
+ currentUserId() {
+ return window.gon.current_user_id;
+ },
+ currentUserFullName() {
+ return window.gon.current_user_fullname;
+ },
+ canAwardEmoji() {
+ return this.note.userPermissions.awardEmoji;
+ },
+ awards() {
+ return this.note.awardEmoji.nodes.map((award) => {
+ return {
+ ...award,
+ user: {
+ ...award.user,
+ id: getIdFromGraphQLId(award.user.id),
+ },
+ };
+ });
+ },
author() {
return this.note.author;
},
@@ -124,6 +160,93 @@ export default {
this.$emit('error', data.errors[0]);
}
},
+ isEmojiPresentForCurrentUser(name) {
+ return (
+ this.awards.findIndex(
+ (emoji) => emoji.name === name && emoji.user.id === this.currentUserId,
+ ) > -1
+ );
+ },
+ /**
+ * Prepare award emoji nodes based on emoji name
+ * and whether the user has toggled the emoji off or on
+ */
+ getAwardEmojiNodes(name, toggledOn) {
+ // If the emoji toggled on, add the emoji
+ if (toggledOn) {
+ // If emoji is already present in award list, no action is needed
+ if (this.isEmojiPresentForCurrentUser(name)) {
+ return this.note.awardEmoji.nodes;
+ }
+
+ // else make a copy of unmutable list and return the list after adding the new emoji
+ const awardEmojiNodes = [...this.note.awardEmoji.nodes];
+ awardEmojiNodes.push({
+ name,
+ __typename: 'AwardEmoji',
+ user: {
+ id: convertToGraphQLId(TYPENAME_USER, this.currentUserId),
+ name: this.currentUserFullName,
+ __typename: 'UserCore',
+ },
+ });
+
+ return awardEmojiNodes;
+ }
+
+ // else just filter the emoji
+ return this.note.awardEmoji.nodes.filter(
+ (emoji) =>
+ !(emoji.name === name && getIdFromGraphQLId(emoji.user.id) === this.currentUserId),
+ );
+ },
+ handleAwardEmoji(name) {
+ this.$apollo
+ .mutate({
+ mutation: designNoteAwardEmojiToggleMutation,
+ variables: {
+ name,
+ awardableId: this.note.id,
+ },
+ optimisticResponse: {
+ awardEmojiToggle: {
+ errors: [],
+ toggledOn: !this.isEmojiPresentForCurrentUser(name),
+ },
+ },
+ update: (
+ cache,
+ {
+ data: {
+ awardEmojiToggle: { toggledOn },
+ },
+ },
+ ) => {
+ const query = {
+ query: getDesignQuery,
+ variables: this.designVariables,
+ };
+
+ const sourceData = cache.readQuery(query);
+
+ const newData = produce(sourceData, (draftState) => {
+ const {
+ awardEmoji,
+ } = draftState.project.issue.designCollection.designs.nodes[0].discussions.nodes
+ .find((d) => d.id === this.note.discussion.id)
+ .notes.nodes.find((n) => n.id === this.note.id);
+
+ awardEmoji.nodes = this.getAwardEmojiNodes(name, toggledOn);
+ });
+
+ cache.writeQuery({ ...query, data: newData });
+ },
+ })
+ .catch((error) => {
+ Sentry.captureException(error);
+ this.$emit('error', error);
+ });
+ },
},
updateNoteMutation,
};
@@ -164,8 +287,31 @@ export default {
</gl-link>
</span>
</div>
- <div class="gl-display-flex gl-align-items-baseline gl-mt-n2 gl-mr-n2">
+ <div class="gl-display-flex gl-align-items-flex-start gl-mt-n2 gl-mr-n2">
<slot name="resolve-discussion"></slot>
+ <emoji-picker
+ v-if="canAwardEmoji"
+ toggle-class="note-action-button note-emoji-button btn-icon btn-default-tertiary"
+ boundary="viewport"
+ :right="false"
+ data-testid="note-emoji-button"
+ @click="handleAwardEmoji"
+ >
+ <template #button-content>
+ <gl-icon
+ class="award-control-icon-neutral gl-button-icon gl-icon"
+ name="slight-smile"
+ />
+ <gl-icon
+ class="award-control-icon-positive gl-button-icon gl-icon gl-left-3!"
+ name="smiley"
+ />
+ <gl-icon
+ class="award-control-icon-super-positive gl-button-icon gl-icon gl-left-3!"
+ name="smile"
+ />
+ </template>
+ </emoji-picker>
<gl-button
v-if="isEditingAndHasPermissions"
v-gl-tooltip
@@ -202,8 +348,14 @@ export default {
></div>
<slot name="resolved-status"></slot>
</template>
+ <design-note-awards-list
+ v-if="awards.length"
+ :awards="awards"
+ :can-award-emoji="note.userPermissions.awardEmoji"
+ @award="handleAwardEmoji"
+ />
<design-reply-form
- v-else
+ v-if="isEditing"
:markdown-preview-path="markdownPreviewPath"
:design-note-mutation="$options.updateNoteMutation"
:mutation-variables="mutationVariables"
diff --git a/app/assets/javascripts/design_management/components/design_notes/design_note_awards_list.vue b/app/assets/javascripts/design_management/components/design_notes/design_note_awards_list.vue
new file mode 100644
index 00000000000..f5456f47410
--- /dev/null
+++ b/app/assets/javascripts/design_management/components/design_notes/design_note_awards_list.vue
@@ -0,0 +1,34 @@
+<script>
+import AwardsList from '~/vue_shared/components/awards_list.vue';
+
+export default {
+ components: {
+ AwardsList,
+ },
+ props: {
+ awards: {
+ type: Array,
+ required: true,
+ },
+ canAwardEmoji: {
+ type: Boolean,
+ required: true,
+ },
+ },
+ computed: {
+ currentUserId() {
+ return window.gon.current_user_id;
+ },
+ },
+};
+</script>
+
+<template>
+ <awards-list
+ :awards="awards"
+ :can-award-emoji="canAwardEmoji"
+ :current-user-id="currentUserId"
+ class="gl-px-2 gl-mt-5"
+ @award="$emit('award', $event)"
+ />
+</template>
diff --git a/app/assets/javascripts/design_management/graphql/fragments/design_note.fragment.graphql b/app/assets/javascripts/design_management/graphql/fragments/design_note.fragment.graphql
index 28224671326..9af4733d5dc 100644
--- a/app/assets/javascripts/design_management/graphql/fragments/design_note.fragment.graphql
+++ b/app/assets/javascripts/design_management/graphql/fragments/design_note.fragment.graphql
@@ -11,6 +11,15 @@ fragment DesignNote on Note {
bodyHtml
createdAt
resolved
+ awardEmoji {
+ nodes {
+ name
+ user {
+ id
+ name
+ }
+ }
+ }
position {
diffRefs {
...DesignDiffRefs
diff --git a/app/assets/javascripts/design_management/graphql/fragments/note_permissions.fragment.graphql b/app/assets/javascripts/design_management/graphql/fragments/note_permissions.fragment.graphql
index e599ab19c2d..acc52e5de59 100644
--- a/app/assets/javascripts/design_management/graphql/fragments/note_permissions.fragment.graphql
+++ b/app/assets/javascripts/design_management/graphql/fragments/note_permissions.fragment.graphql
@@ -1,4 +1,5 @@
fragment DesignNotePermissions on NotePermissions {
adminNote
repositionNote
+ awardEmoji
}
diff --git a/app/assets/javascripts/design_management/graphql/mutations/design_note_award_emoji_toggle.mutation.graphql b/app/assets/javascripts/design_management/graphql/mutations/design_note_award_emoji_toggle.mutation.graphql
new file mode 100644
index 00000000000..3e274d0b65f
--- /dev/null
+++ b/app/assets/javascripts/design_management/graphql/mutations/design_note_award_emoji_toggle.mutation.graphql
@@ -0,0 +1,6 @@
+mutation designNoteNoteToggleAwardEmoji($awardableId: AwardableID!, $name: String!) {
+ awardEmojiToggle(input: { awardableId: $awardableId, name: $name }) {
+ errors
+ toggledOn
+ }
+}