Commit de54e617 authored by Ezekiel Kigbo's avatar Ezekiel Kigbo Committed by Nathan Friend

Fixes the persistent speech_balloon after removing status

Expose status field on the user_basic entity and updates
the note_user_entity
parent a0e44758
...@@ -85,7 +85,10 @@ export default { ...@@ -85,7 +85,10 @@ export default {
}; };
}, },
authorStatus() { authorStatus() {
return this.author.status_tooltip_html; if (this.author?.show_status) {
return this.author.status_tooltip_html;
}
return false;
}, },
authorIsBusy() { authorIsBusy() {
const { status } = this.author; const { status } = this.author;
......
...@@ -37,10 +37,4 @@ module ProfilesHelper ...@@ -37,10 +37,4 @@ module ProfilesHelper
def user_status_set_to_busy?(status) def user_status_set_to_busy?(status)
status&.availability == availability_values[:busy] status&.availability == availability_values[:busy]
end end
def show_status_emoji?(status)
return false unless status
status.message.present? || status.emoji != UserStatus::DEFAULT_EMOJI
end
end end
...@@ -60,6 +60,12 @@ module UsersHelper ...@@ -60,6 +60,12 @@ module UsersHelper
"access:#{max_project_member_access(project)}" "access:#{max_project_member_access(project)}"
end end
def show_status_emoji?(status)
return false unless status
status.message.present? || status.emoji != UserStatus::DEFAULT_EMOJI
end
def user_status(user) def user_status(user)
return unless user return unless user
......
...@@ -8,12 +8,18 @@ module UserStatusTooltip ...@@ -8,12 +8,18 @@ module UserStatusTooltip
include UsersHelper include UsersHelper
included do included do
expose :user_status_if_loaded, as: :status_tooltip_html expose :status_tooltip_html, if: -> (*) { status_loaded? } do |user|
user_status(user)
end
expose :show_status do |user|
status_loaded? && show_status_emoji?(user.status)
end
def user_status_if_loaded private
return unless object.association(:status).loaded?
user_status(object) def status_loaded?
object.association(:status).loaded?
end end
end end
end end
...@@ -11,6 +11,7 @@ ...@@ -11,6 +11,7 @@
"name": { "type": "string" }, "name": { "type": "string" },
"username": { "type": "string" }, "username": { "type": "string" },
"status_tooltip_html": { "$ref": "../../../../../../spec/fixtures/api/schemas/types/nullable_string.json" }, "status_tooltip_html": { "$ref": "../../../../../../spec/fixtures/api/schemas/types/nullable_string.json" },
"show_status": { "type": "boolean" },
"is_gitlab_employee": { "type": "boolean" } "is_gitlab_employee": { "type": "boolean" }
}, },
"additionalProperties": false, "additionalProperties": false,
......
...@@ -21,6 +21,7 @@ ...@@ -21,6 +21,7 @@
"name": { "type": "string" }, "name": { "type": "string" },
"username": { "type": "string" }, "username": { "type": "string" },
"status_tooltip_html": { "$ref": "../../../../../../spec/fixtures/api/schemas/types/nullable_string.json" }, "status_tooltip_html": { "$ref": "../../../../../../spec/fixtures/api/schemas/types/nullable_string.json" },
"show_status": { "type": "boolean" },
"is_gitlab_employee": { "type": "boolean" } "is_gitlab_employee": { "type": "boolean" }
}, },
"additionalProperties": false "additionalProperties": false
......
...@@ -3,6 +3,8 @@ ...@@ -3,6 +3,8 @@
require 'spec_helper' require 'spec_helper'
RSpec.describe 'User edit profile' do RSpec.describe 'User edit profile' do
include Spec::Support::Helpers::Features::NotesHelpers
let(:user) { create(:user) } let(:user) { create(:user) }
before do before do
...@@ -398,6 +400,45 @@ RSpec.describe 'User edit profile' do ...@@ -398,6 +400,45 @@ RSpec.describe 'User edit profile' do
end end
end end
context 'note header' do
let(:project) { create(:project_empty_repo, :public) }
let(:issue) { create(:issue, project: project) }
let(:emoji) { "stuffed_flatbread" }
before do
project.add_guest(user)
create(:user_status, user: user, message: 'Taking notes', emoji: emoji)
visit(project_issue_path(project, issue))
add_note("This is a comment")
visit(project_issue_path(project, issue))
wait_for_requests
end
it 'displays the status emoji' do
first_note = page.find_all(".main-notes-list .timeline-entry").first
expect(first_note).to have_emoji(emoji)
end
it 'clears the status emoji' do
open_edit_status_modal
page.within "#set-user-status-modal" do
click_button 'Remove status'
end
visit(project_issue_path(project, issue))
wait_for_requests
first_note = page.find_all(".main-notes-list .timeline-entry").first
expect(first_note).not_to have_css('.user-status-emoji')
end
end
context 'with set_user_availability_status feature flag disabled' do context 'with set_user_availability_status feature flag disabled' do
before do before do
stub_feature_flags(set_user_availability_status: false) stub_feature_flags(set_user_availability_status: false)
......
...@@ -15,6 +15,7 @@ ...@@ -15,6 +15,7 @@
"path": { "type": "string" }, "path": { "type": "string" },
"name": { "type": "string" }, "name": { "type": "string" },
"username": { "type": "string" }, "username": { "type": "string" },
"status_tooltip_html": { "$ref": "../types/nullable_string.json" } "status_tooltip_html": { "$ref": "../types/nullable_string.json" },
"show_status": { "type": "boolean" }
} }
} }
...@@ -22,6 +22,10 @@ describe('NoteHeader component', () => { ...@@ -22,6 +22,10 @@ describe('NoteHeader component', () => {
const findTimestamp = () => wrapper.find({ ref: 'noteTimestamp' }); const findTimestamp = () => wrapper.find({ ref: 'noteTimestamp' });
const findConfidentialIndicator = () => wrapper.find('[data-testid="confidentialIndicator"]'); const findConfidentialIndicator = () => wrapper.find('[data-testid="confidentialIndicator"]');
const findSpinner = () => wrapper.find({ ref: 'spinner' }); const findSpinner = () => wrapper.find({ ref: 'spinner' });
const findAuthorStatus = () => wrapper.find({ ref: 'authorStatus' });
const statusHtml =
'"<span class="user-status-emoji has-tooltip" title="foo bar" data-html="true" data-placement="top"><gl-emoji title="basketball and hoop" data-name="basketball" data-unicode-version="6.0">🏀</gl-emoji></span>"';
const author = { const author = {
avatar_url: null, avatar_url: null,
...@@ -30,6 +34,8 @@ describe('NoteHeader component', () => { ...@@ -30,6 +34,8 @@ describe('NoteHeader component', () => {
path: '/root', path: '/root',
state: 'active', state: 'active',
username: 'root', username: 'root',
show_status: true,
status_tooltip_html: statusHtml,
status: { status: {
availability: '', availability: '',
}, },
...@@ -109,6 +115,32 @@ describe('NoteHeader component', () => { ...@@ -109,6 +115,32 @@ describe('NoteHeader component', () => {
expect(wrapper.find('.js-user-link').text()).toContain('(Busy)'); expect(wrapper.find('.js-user-link').text()).toContain('(Busy)');
}); });
it('renders author status', () => {
createComponent({ author });
expect(findAuthorStatus().exists()).toBe(true);
});
it('does not render author status if show_status=false', () => {
createComponent({
author: { ...author, status: { availability: AVAILABILITY_STATUS.BUSY }, show_status: false },
});
expect(findAuthorStatus().exists()).toBe(false);
});
it('does not render author status if status_tooltip_html=null', () => {
createComponent({
author: {
...author,
status: { availability: AVAILABILITY_STATUS.BUSY },
status_tooltip_html: null,
},
});
expect(findAuthorStatus().exists()).toBe(false);
});
it('renders deleted user text if author is not passed as a prop', () => { it('renders deleted user text if author is not passed as a prop', () => {
createComponent(); createComponent();
...@@ -206,13 +238,12 @@ describe('NoteHeader component', () => { ...@@ -206,13 +238,12 @@ describe('NoteHeader component', () => {
createComponent({ createComponent({
author: { author: {
...author, ...author,
status_tooltip_html: status_tooltip_html: statusHtml,
'"<span class="user-status-emoji has-tooltip" title="foo bar" data-html="true" data-placement="top"><gl-emoji title="basketball and hoop" data-name="basketball" data-unicode-version="6.0">🏀</gl-emoji></span>"',
}, },
}); });
return nextTick().then(() => { return nextTick().then(() => {
const authorStatus = wrapper.find({ ref: 'authorStatus' }); const authorStatus = findAuthorStatus();
authorStatus.trigger('mouseenter'); authorStatus.trigger('mouseenter');
expect(authorStatus.find('gl-emoji').attributes('title')).toBeUndefined(); expect(authorStatus.find('gl-emoji').attributes('title')).toBeUndefined();
......
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