Commit 31406b17 authored by Vitali Tatarintev's avatar Vitali Tatarintev

Merge branch 'set-user-availability-be' into 'master'

Add availability to user status

See merge request gitlab-org/gitlab!45888
parents b18bd203 cf13d476
......@@ -127,7 +127,7 @@ class ProfilesController < Profiles::ApplicationController
:include_private_contributions,
:timezone,
:job_title,
status: [:emoji, :message]
status: [:emoji, :message, :availability]
)
end
end
# frozen_string_literal: true
module Types
class AvailabilityEnum < BaseEnum
graphql_name 'AvailabilityEnum'
description 'User availability status'
::UserStatus.availabilities.keys.each do |availability_value|
value availability_value.upcase, value: availability_value, description: availability_value.titleize
end
end
end
......@@ -11,5 +11,7 @@ module Types
description: 'User status message'
field :emoji, GraphQL::STRING_TYPE, null: true,
description: 'String representation of emoji'
field :availability, Types::AvailabilityEnum, null: false,
description: 'User availability status'
end
end
......@@ -9,6 +9,8 @@ class UserStatus < ApplicationRecord
belongs_to :user
enum availability: { not_set: 0, busy: 1 }
validates :user, presence: true
validates :emoji, inclusion: { in: Gitlab::Emoji.emojis_names }
validates :message, length: { maximum: 100 }, allow_blank: true
......
......@@ -14,7 +14,7 @@ module Users
def execute
return false unless can?(current_user, :update_user_status, target_user)
if params[:emoji].present? || params[:message].present?
if params[:emoji].present? || params[:message].present? || params[:availability].present?
set_status
else
remove_status
......@@ -25,6 +25,9 @@ module Users
def set_status
params[:emoji] = UserStatus::DEFAULT_EMOJI if params[:emoji].blank?
params.delete(:availability) if params[:availability].blank?
return false if params[:availability].present? && UserStatus.availabilities.keys.exclude?(params[:availability])
user_status.update(params)
end
......
---
title: Add availability to user status
merge_request: 45888
author:
type: added
# frozen_string_literal: true
class AddAvailabilityToUserStatuses < ActiveRecord::Migration[6.0]
DOWNTIME = false
def change
add_column :user_statuses, :availability, :integer, limit: 2, default: 0, null: false
end
end
aa15aad0b51f313f3cd59e1065023146fe53c6bd50319656ae992f8f43e1525e
\ No newline at end of file
......@@ -16782,7 +16782,8 @@ CREATE TABLE user_statuses (
cached_markdown_version integer,
emoji character varying DEFAULT 'speech_balloon'::character varying NOT NULL,
message character varying(100),
message_html character varying
message_html character varying,
availability smallint DEFAULT 0 NOT NULL
);
CREATE SEQUENCE user_statuses_user_id_seq
......
......@@ -927,6 +927,21 @@ type AlertTodoCreatePayload {
todo: Todo
}
"""
User availability status
"""
enum AvailabilityEnum {
"""
Busy
"""
BUSY
"""
Not Set
"""
NOT_SET
}
"""
An emoji awarded by a user
"""
......@@ -21450,6 +21465,11 @@ enum UserState {
}
type UserStatus {
"""
User availability status
"""
availability: AvailabilityEnum!
"""
String representation of emoji
"""
......
......@@ -2391,6 +2391,29 @@
"enumValues": null,
"possibleTypes": null
},
{
"kind": "ENUM",
"name": "AvailabilityEnum",
"description": "User availability status",
"fields": null,
"inputFields": null,
"interfaces": null,
"enumValues": [
{
"name": "NOT_SET",
"description": "Not Set",
"isDeprecated": false,
"deprecationReason": null
},
{
"name": "BUSY",
"description": "Busy",
"isDeprecated": false,
"deprecationReason": null
}
],
"possibleTypes": null
},
{
"kind": "OBJECT",
"name": "AwardEmoji",
......@@ -62028,6 +62051,24 @@
"name": "UserStatus",
"description": null,
"fields": [
{
"name": "availability",
"description": "User availability status",
"args": [
],
"type": {
"kind": "NON_NULL",
"name": null,
"ofType": {
"kind": "ENUM",
"name": "AvailabilityEnum",
"ofType": null
}
},
"isDeprecated": false,
"deprecationReason": null
},
{
"name": "emoji",
"description": "String representation of emoji",
......@@ -2990,6 +2990,7 @@ Autogenerated return type of UpdateSnippet.
| Field | Type | Description |
| ----- | ---- | ----------- |
| `availability` | AvailabilityEnum! | User availability status |
| `emoji` | String | String representation of emoji |
| `message` | String | User status message |
| `messageHtml` | String | HTML of the user status message |
......@@ -3318,6 +3319,15 @@ Alert status values.
| `RESOLVED` | Resolved status |
| `TRIGGERED` | Triggered status |
### AvailabilityEnum
User availability status.
| Value | Description |
| ----- | ----------- |
| `BUSY` | Busy |
| `NOT_SET` | Not Set |
### BlobViewersType
Types of blob viewers.
......
......@@ -5,6 +5,7 @@ module API
class UserStatus < Grape::Entity
expose :emoji
expose :message
expose :availability
expose :message_html do |entity|
MarkupHelper.markdown_field(entity, :message)
end
......
......@@ -952,6 +952,7 @@ module API
params do
optional :emoji, type: String, desc: "The emoji to set on the status"
optional :message, type: String, desc: "The status message to set"
optional :availability, type: String, desc: "The availability of user to set"
end
put "status", feature_category: :users do
forbidden! unless can?(current_user, :update_user_status, current_user)
......
......@@ -84,9 +84,10 @@ RSpec.describe ProfilesController, :request_store do
it 'allows setting a user status' do
sign_in(user)
put :update, params: { user: { status: { message: 'Working hard!' } } }
put :update, params: { user: { status: { message: 'Working hard!', availability: 'busy' } } }
expect(user.reload.status.message).to eq('Working hard!')
expect(user.reload.status.availability).to eq('busy')
expect(response).to have_gitlab_http_status(:found)
end
......
# frozen_string_literal: true
require 'spec_helper'
RSpec.describe GitlabSchema.types['AvailabilityEnum'] do
specify { expect(described_class.graphql_name).to eq('AvailabilityEnum') }
it 'exposes all the existing access levels' do
expect(described_class.values.keys).to match_array(%w[NOT_SET BUSY])
end
end
......@@ -10,6 +10,7 @@ RSpec.describe Types::UserStatusType do
emoji
message
message_html
availability
]
expect(described_class).to have_graphql_fields(*expected_fields)
......
......@@ -59,6 +59,7 @@ RSpec.describe 'getting user information' do
let(:user_params) { { username: user.username } }
before do
create(:user_status, user: user)
post_graphql(query, current_user: current_user)
end
......@@ -76,9 +77,15 @@ RSpec.describe 'getting user information' do
'username' => presenter.username,
'webUrl' => presenter.web_url,
'avatarUrl' => presenter.avatar_url,
'status' => presenter.status,
'email' => presenter.email
))
expect(graphql_data['user']['status']).to match(
a_hash_including(
'emoji' => presenter.status.emoji,
'message' => presenter.status.message,
'availability' => presenter.status.availability.upcase
))
end
describe 'assignedMergeRequests' do
......
......@@ -9,13 +9,14 @@ RSpec.describe Users::SetStatusService do
describe '#execute' do
context 'when params are set' do
let(:params) { { emoji: 'taurus', message: 'a random status' } }
let(:params) { { emoji: 'taurus', message: 'a random status', availability: 'busy' } }
it 'creates a status' do
service.execute
expect(current_user.status.emoji).to eq('taurus')
expect(current_user.status.message).to eq('a random status')
expect(current_user.status.availability).to eq('busy')
end
it 'updates a status if it already existed' do
......@@ -25,6 +26,26 @@ RSpec.describe Users::SetStatusService do
expect(current_user.status.message).to eq('a random status')
end
it 'returns true' do
create(:user_status, user: current_user)
expect(service.execute).to be(true)
end
context 'when the given availability value is not valid' do
let(:params) { { availability: 'not a valid value' } }
it 'does not update the status' do
user_status = create(:user_status, user: current_user)
expect { service.execute }.not_to change { user_status.reload }
end
it 'returns false' do
create(:user_status, user: current_user)
expect(service.execute).to be(false)
end
end
context 'for another user' do
let(:target_user) { create(:user) }
let(:params) do
......
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