Merge branch 'feat/linear-backend' into feature/cw-3271
This commit is contained in:
@@ -3,29 +3,29 @@ class Api::V1::Accounts::Integrations::LinearController < Api::V1::Accounts::Bas
|
||||
|
||||
def teams
|
||||
teams = linear_processor_service.teams
|
||||
if teams.is_a?(Hash) && teams[:error]
|
||||
if teams[:error]
|
||||
render json: { error: teams[:error] }, status: :unprocessable_entity
|
||||
else
|
||||
render json: teams, status: :ok
|
||||
render json: teams[:data], status: :ok
|
||||
end
|
||||
end
|
||||
|
||||
def team_entities
|
||||
team_id = permitted_params[:team_id]
|
||||
entites = linear_processor_service.team_entities(team_id)
|
||||
if entites.is_a?(Hash) && entites[:error]
|
||||
render json: { error: entites[:error] }, status: :unprocessable_entity
|
||||
team_entities = linear_processor_service.team_entities(team_id)
|
||||
if team_entities[:error]
|
||||
render json: { error: team_entities[:error] }, status: :unprocessable_entity
|
||||
else
|
||||
render json: entites, status: :ok
|
||||
render json: team_entities[:data], status: :ok
|
||||
end
|
||||
end
|
||||
|
||||
def create_issue
|
||||
issue = linear_processor_service.create_issue(permitted_params)
|
||||
if issue.is_a?(Hash) && issue[:error]
|
||||
if issue[:error]
|
||||
render json: { error: issue[:error] }, status: :unprocessable_entity
|
||||
else
|
||||
render json: issue, status: :ok
|
||||
render json: issue[:data], status: :ok
|
||||
end
|
||||
end
|
||||
|
||||
@@ -33,10 +33,10 @@ class Api::V1::Accounts::Integrations::LinearController < Api::V1::Accounts::Bas
|
||||
issue_id = permitted_params[:issue_id]
|
||||
title = permitted_params[:title]
|
||||
issue = linear_processor_service.link_issue(conversation_link, issue_id, title)
|
||||
if issue.is_a?(Hash) && issue[:error]
|
||||
if issue[:error]
|
||||
render json: { error: issue[:error] }, status: :unprocessable_entity
|
||||
else
|
||||
render json: issue, status: :ok
|
||||
render json: issue[:data], status: :ok
|
||||
end
|
||||
end
|
||||
|
||||
@@ -44,20 +44,20 @@ class Api::V1::Accounts::Integrations::LinearController < Api::V1::Accounts::Bas
|
||||
link_id = permitted_params[:link_id]
|
||||
issue = linear_processor_service.unlink_issue(link_id)
|
||||
|
||||
if issue.is_a?(Hash) && issue[:error]
|
||||
if issue[:error]
|
||||
render json: { error: issue[:error] }, status: :unprocessable_entity
|
||||
else
|
||||
render json: issue, status: :ok
|
||||
render json: issue[:data], status: :ok
|
||||
end
|
||||
end
|
||||
|
||||
def linked_issue
|
||||
issues = linear_processor_service.linked_issue(conversation_link)
|
||||
issues = linear_processor_service.linked_issues(conversation_link)
|
||||
|
||||
if issues.is_a?(Hash) && issues[:error]
|
||||
if issues[:error]
|
||||
render json: { error: issues[:error] }, status: :unprocessable_entity
|
||||
else
|
||||
render json: issues, status: :ok
|
||||
render json: issues[:data], status: :ok
|
||||
end
|
||||
end
|
||||
|
||||
@@ -66,10 +66,10 @@ class Api::V1::Accounts::Integrations::LinearController < Api::V1::Accounts::Bas
|
||||
|
||||
term = params[:q]
|
||||
issues = linear_processor_service.search_issue(term)
|
||||
if issues.is_a?(Hash) && issues[:error]
|
||||
if issues[:error]
|
||||
render json: { error: issues[:error] }, status: :unprocessable_entity
|
||||
else
|
||||
render json: issues, status: :ok
|
||||
render json: issues[:data], status: :ok
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
@@ -3,9 +3,9 @@ class Integrations::Linear::ProcessorService
|
||||
|
||||
def teams
|
||||
response = linear_client.teams
|
||||
return response if response[:error]
|
||||
return { error: response[:error] } if response[:error]
|
||||
|
||||
response['teams']['nodes'].map(&:as_json)
|
||||
{ data: response['teams']['nodes'].map(&:as_json) }
|
||||
end
|
||||
|
||||
def team_entities(team_id)
|
||||
@@ -13,10 +13,12 @@ class Integrations::Linear::ProcessorService
|
||||
return response if response[:error]
|
||||
|
||||
{
|
||||
users: response['users']['nodes'].map(&:as_json),
|
||||
projects: response['projects']['nodes'].map(&:as_json),
|
||||
states: response['workflowStates']['nodes'].map(&:as_json),
|
||||
labels: response['issueLabels']['nodes'].map(&:as_json)
|
||||
data: {
|
||||
users: response['users']['nodes'].map(&:as_json),
|
||||
projects: response['projects']['nodes'].map(&:as_json),
|
||||
states: response['workflowStates']['nodes'].map(&:as_json),
|
||||
labels: response['issueLabels']['nodes'].map(&:as_json)
|
||||
}
|
||||
}
|
||||
end
|
||||
|
||||
@@ -25,8 +27,8 @@ class Integrations::Linear::ProcessorService
|
||||
return response if response[:error]
|
||||
|
||||
{
|
||||
id: response['issueCreate']['issue']['id'],
|
||||
title: response['issueCreate']['issue']['title']
|
||||
data: { id: response['issueCreate']['issue']['id'],
|
||||
title: response['issueCreate']['issue']['title'] }
|
||||
}
|
||||
end
|
||||
|
||||
@@ -35,9 +37,11 @@ class Integrations::Linear::ProcessorService
|
||||
return response if response[:error]
|
||||
|
||||
{
|
||||
id: issue_id,
|
||||
link: link,
|
||||
link_id: response.with_indifferent_access[:attachmentLinkURL][:attachment][:id]
|
||||
data: {
|
||||
id: issue_id,
|
||||
link: link,
|
||||
link_id: response.with_indifferent_access[:attachmentLinkURL][:attachment][:id]
|
||||
}
|
||||
}
|
||||
end
|
||||
|
||||
@@ -46,7 +50,7 @@ class Integrations::Linear::ProcessorService
|
||||
return response if response[:error]
|
||||
|
||||
{
|
||||
link_id: link_id
|
||||
data: { link_id: link_id }
|
||||
}
|
||||
end
|
||||
|
||||
@@ -55,14 +59,14 @@ class Integrations::Linear::ProcessorService
|
||||
|
||||
return response if response[:error]
|
||||
|
||||
response['searchIssues']['nodes'].map(&:as_json)
|
||||
{ data: response['searchIssues']['nodes'].map(&:as_json) }
|
||||
end
|
||||
|
||||
def linked_issue(url)
|
||||
response = linear_client.linked_issue(url)
|
||||
def linked_issues(url)
|
||||
response = linear_client.linked_issues(url)
|
||||
return response if response[:error]
|
||||
|
||||
response['attachmentsForURL']['nodes'].map(&:as_json)
|
||||
{ data: response['attachmentsForURL']['nodes'].map(&:as_json) }
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
+8
-11
@@ -1,6 +1,3 @@
|
||||
require_relative 'linear_queries'
|
||||
require_relative 'linear_mutations'
|
||||
|
||||
class Linear
|
||||
BASE_URL = 'https://api.linear.app/graphql'.freeze
|
||||
PRIORITY_LEVELS = (0..4).to_a
|
||||
@@ -12,7 +9,7 @@ class Linear
|
||||
|
||||
def teams
|
||||
query = {
|
||||
query: LinearQueries::TEAMS_QUERY
|
||||
query: Linear::Queries::TEAMS_QUERY
|
||||
}
|
||||
response = post(query)
|
||||
process_response(response)
|
||||
@@ -22,7 +19,7 @@ class Linear
|
||||
raise ArgumentError, 'Missing team id' if team_id.blank?
|
||||
|
||||
query = {
|
||||
query: LinearQueries.team_entities_query(team_id)
|
||||
query: Linear::Queries.team_entities_query(team_id)
|
||||
}
|
||||
response = post(query)
|
||||
process_response(response)
|
||||
@@ -32,17 +29,17 @@ class Linear
|
||||
raise ArgumentError, 'Missing search term' if term.blank?
|
||||
|
||||
query = {
|
||||
query: LinearQueries.search_issue(term)
|
||||
query: Linear::Queries.search_issue(term)
|
||||
}
|
||||
response = post(query)
|
||||
process_response(response)
|
||||
end
|
||||
|
||||
def linked_issue(url)
|
||||
def linked_issues(url)
|
||||
raise ArgumentError, 'Missing link' if url.blank?
|
||||
|
||||
query = {
|
||||
query: LinearQueries.linked_issue(url)
|
||||
query: Linear::Queries.linked_issues(url)
|
||||
}
|
||||
response = post(query)
|
||||
process_response(response)
|
||||
@@ -61,7 +58,7 @@ class Linear
|
||||
priority: params[:priority],
|
||||
labelIds: params[:label_ids]
|
||||
}.compact
|
||||
mutation = LinearMutations.issue_create(variables)
|
||||
mutation = Linear::Mutations.issue_create(variables)
|
||||
response = post({ query: mutation })
|
||||
process_response(response)
|
||||
end
|
||||
@@ -71,7 +68,7 @@ class Linear
|
||||
raise ArgumentError, 'Missing issue id' if issue_id.blank?
|
||||
|
||||
payload = {
|
||||
query: LinearMutations.issue_link(issue_id, link, title)
|
||||
query: Linear::Mutations.issue_link(issue_id, link, title)
|
||||
}
|
||||
response = post(payload)
|
||||
process_response(response)
|
||||
@@ -81,7 +78,7 @@ class Linear
|
||||
raise ArgumentError, 'Missing link id' if link_id.blank?
|
||||
|
||||
payload = {
|
||||
query: LinearMutations.unlink_issue(link_id)
|
||||
query: Linear::Mutations.unlink_issue(link_id)
|
||||
}
|
||||
response = post(payload)
|
||||
process_response(response)
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
module LinearMutations
|
||||
module Linear::Mutations
|
||||
def self.graphql_value(value)
|
||||
case value
|
||||
when String
|
||||
@@ -1,4 +1,4 @@
|
||||
module LinearQueries
|
||||
module Linear::Queries
|
||||
TEAMS_QUERY = <<~GRAPHQL.freeze
|
||||
query {
|
||||
teams {
|
||||
@@ -60,7 +60,7 @@ module LinearQueries
|
||||
GRAPHQL
|
||||
end
|
||||
|
||||
def self.linked_issue(url)
|
||||
def self.linked_issues(url)
|
||||
<<~GRAPHQL
|
||||
query {
|
||||
attachmentsForURL(url: "#{url}") {
|
||||
@@ -15,7 +15,7 @@ RSpec.describe 'Linear Integration API', type: :request do
|
||||
describe 'GET /api/v1/accounts/:account_id/integrations/linear/teams' do
|
||||
context 'when it is an authenticated user' do
|
||||
context 'when data is retrieved successfully' do
|
||||
let(:teams_data) { [{ 'id' => 'team1', 'name' => 'Team One' }] }
|
||||
let(:teams_data) { { data: [{ 'id' => 'team1', 'name' => 'Team One' }] } }
|
||||
|
||||
it 'returns team data' do
|
||||
allow(processor_service).to receive(:teams).and_return(teams_data)
|
||||
@@ -46,12 +46,12 @@ RSpec.describe 'Linear Integration API', type: :request do
|
||||
context 'when it is an authenticated user' do
|
||||
context 'when data is retrieved successfully' do
|
||||
let(:team_entities_data) do
|
||||
{
|
||||
{ data: {
|
||||
users: [{ 'id' => 'user1', 'name' => 'User One' }],
|
||||
projects: [{ 'id' => 'project1', 'name' => 'Project One' }],
|
||||
states: [{ 'id' => 'state1', 'name' => 'State One' }],
|
||||
labels: [{ 'id' => 'label1', 'name' => 'Label One' }]
|
||||
}
|
||||
} }
|
||||
end
|
||||
|
||||
it 'returns team entities data' do
|
||||
@@ -96,7 +96,7 @@ RSpec.describe 'Linear Integration API', type: :request do
|
||||
|
||||
context 'when it is an authenticated user' do
|
||||
context 'when the issue is created successfully' do
|
||||
let(:created_issue) { { 'id' => 'issue1', 'title' => 'Sample Issue' } }
|
||||
let(:created_issue) { { data: { 'id' => 'issue1', 'title' => 'Sample Issue' } } }
|
||||
|
||||
it 'returns the created issue' do
|
||||
allow(processor_service).to receive(:create_issue).with(issue_params.stringify_keys).and_return(created_issue)
|
||||
@@ -131,7 +131,7 @@ RSpec.describe 'Linear Integration API', type: :request do
|
||||
|
||||
context 'when it is an authenticated user' do
|
||||
context 'when the issue is linked successfully' do
|
||||
let(:linked_issue) { { 'id' => 'issue1', 'link' => 'https://linear.app/issue1' } }
|
||||
let(:linked_issue) { { data: { 'id' => 'issue1', 'link' => 'https://linear.app/issue1' } } }
|
||||
|
||||
it 'returns the linked issue' do
|
||||
allow(processor_service).to receive(:link_issue).with(link, issue_id, title).and_return(linked_issue)
|
||||
@@ -163,7 +163,7 @@ RSpec.describe 'Linear Integration API', type: :request do
|
||||
|
||||
context 'when it is an authenticated user' do
|
||||
context 'when the issue is unlinked successfully' do
|
||||
let(:unlinked_issue) { { 'id' => 'issue1', 'link' => 'https://linear.app/issue1' } }
|
||||
let(:unlinked_issue) { { data: { 'id' => 'issue1', 'link' => 'https://linear.app/issue1' } } }
|
||||
|
||||
it 'returns the unlinked issue' do
|
||||
allow(processor_service).to receive(:unlink_issue).with(link_id).and_return(unlinked_issue)
|
||||
@@ -195,7 +195,7 @@ RSpec.describe 'Linear Integration API', type: :request do
|
||||
|
||||
context 'when it is an authenticated user' do
|
||||
context 'when search is successful' do
|
||||
let(:search_results) { [{ 'id' => 'issue1', 'title' => 'Sample Issue' }] }
|
||||
let(:search_results) { { data: [{ 'id' => 'issue1', 'title' => 'Sample Issue' }] } }
|
||||
|
||||
it 'returns search results' do
|
||||
allow(processor_service).to receive(:search_issue).with(term).and_return(search_results)
|
||||
@@ -228,10 +228,10 @@ RSpec.describe 'Linear Integration API', type: :request do
|
||||
|
||||
context 'when it is an authenticated user' do
|
||||
context 'when linked issue is found' do
|
||||
let(:linked_issue) { [{ 'id' => 'issue1', 'title' => 'Sample Issue' }] }
|
||||
let(:linked_issue) { { data: [{ 'id' => 'issue1', 'title' => 'Sample Issue' }] } }
|
||||
|
||||
it 'returns linked issue' do
|
||||
allow(processor_service).to receive(:linked_issue).with(link).and_return(linked_issue)
|
||||
allow(processor_service).to receive(:linked_issues).with(link).and_return(linked_issue)
|
||||
get "/api/v1/accounts/#{account.id}/integrations/linear/linked_issue",
|
||||
params: { conversation_id: conversation.display_id },
|
||||
headers: agent.create_new_auth_token,
|
||||
@@ -243,7 +243,7 @@ RSpec.describe 'Linear Integration API', type: :request do
|
||||
|
||||
context 'when linked issue is not found' do
|
||||
it 'returns error message' do
|
||||
allow(processor_service).to receive(:linked_issue).with(link).and_return(error: 'error message')
|
||||
allow(processor_service).to receive(:linked_issues).with(link).and_return(error: 'error message')
|
||||
get "/api/v1/accounts/#{account.id}/integrations/linear/linked_issue",
|
||||
params: { conversation_id: conversation.display_id },
|
||||
headers: agent.create_new_auth_token,
|
||||
|
||||
@@ -20,7 +20,7 @@ describe Integrations::Linear::ProcessorService do
|
||||
it 'returns parsed team data' do
|
||||
allow(linear_client).to receive(:teams).and_return(teams_response)
|
||||
result = service.teams
|
||||
expect(result).to contain_exactly({ 'id' => 'team1', 'name' => 'Team One' })
|
||||
expect(result).to eq({ data: [{ 'id' => 'team1', 'name' => 'Team One' }] })
|
||||
end
|
||||
end
|
||||
|
||||
@@ -50,10 +50,10 @@ describe Integrations::Linear::ProcessorService do
|
||||
it 'returns parsed entity data' do
|
||||
allow(linear_client).to receive(:team_entities).with(team_id).and_return(entities_response)
|
||||
result = service.team_entities(team_id)
|
||||
expect(result).to have_key(:users)
|
||||
expect(result).to have_key(:projects)
|
||||
expect(result).to have_key(:states)
|
||||
expect(result).to have_key(:labels)
|
||||
expect(result).to eq({ :data => { :users =>
|
||||
[{ 'id' => 'user1', 'name' => 'User One' }],
|
||||
:projects => [{ 'id' => 'project1', 'name' => 'Project One' }],
|
||||
:states => [], :labels => [{ 'id' => 'bug', 'name' => 'Bug' }] } })
|
||||
end
|
||||
end
|
||||
|
||||
@@ -89,7 +89,7 @@ describe Integrations::Linear::ProcessorService do
|
||||
it 'returns parsed issue data' do
|
||||
allow(linear_client).to receive(:create_issue).with(params).and_return(issue_response)
|
||||
result = service.create_issue(params)
|
||||
expect(result).to eq({ id: 'issue1', title: 'Issue title' })
|
||||
expect(result).to eq({ data: { id: 'issue1', title: 'Issue title' } })
|
||||
end
|
||||
end
|
||||
|
||||
@@ -109,7 +109,7 @@ describe Integrations::Linear::ProcessorService do
|
||||
let(:issue_id) { 'issue1' }
|
||||
let(:title) { 'Title' }
|
||||
let(:link_issue_response) { { id: issue_id, link: link, 'attachmentLinkURL': { 'attachment': { 'id': 'attachment1' } } } }
|
||||
let(:link_response) { { id: issue_id, link: link, link_id: 'attachment1' } }
|
||||
let(:link_response) { { data: { id: issue_id, link: link, link_id: 'attachment1' } } }
|
||||
|
||||
context 'when Linear client returns valid data' do
|
||||
it 'returns parsed link data' do
|
||||
@@ -132,7 +132,7 @@ describe Integrations::Linear::ProcessorService do
|
||||
|
||||
describe '#unlink_issue' do
|
||||
let(:link_id) { 'attachment1' }
|
||||
let(:unlink_response) { { link_id: link_id } }
|
||||
let(:unlink_response) { { data: { link_id: link_id } } }
|
||||
|
||||
context 'when Linear client returns valid data' do
|
||||
it 'returns parsed unlink data' do
|
||||
@@ -165,7 +165,7 @@ describe Integrations::Linear::ProcessorService do
|
||||
it 'returns parsed search data' do
|
||||
allow(linear_client).to receive(:search_issue).with(term).and_return(search_response)
|
||||
result = service.search_issue(term)
|
||||
expect(result).to contain_exactly({ 'id' => 'issue1', 'title' => 'Issue title', 'description' => 'Issue description' })
|
||||
expect(result).to eq({ :data => [{ 'description' => 'Issue description', 'id' => 'issue1', 'title' => 'Issue title' }] })
|
||||
end
|
||||
end
|
||||
|
||||
@@ -180,7 +180,7 @@ describe Integrations::Linear::ProcessorService do
|
||||
end
|
||||
end
|
||||
|
||||
describe '#linked_issue' do
|
||||
describe '#linked_issues' do
|
||||
let(:url) { 'https://example.com' }
|
||||
let(:linked_response) do
|
||||
{
|
||||
@@ -190,9 +190,9 @@ describe Integrations::Linear::ProcessorService do
|
||||
|
||||
context 'when Linear client returns valid data' do
|
||||
it 'returns parsed linked data' do
|
||||
allow(linear_client).to receive(:linked_issue).with(url).and_return(linked_response)
|
||||
result = service.linked_issue(url)
|
||||
expect(result).to contain_exactly({ 'id' => 'attachment1', 'issue' => { 'id' => 'issue1' } })
|
||||
allow(linear_client).to receive(:linked_issues).with(url).and_return(linked_response)
|
||||
result = service.linked_issues(url)
|
||||
expect(result).to eq({ :data => [{ 'id' => 'attachment1', 'issue' => { 'id' => 'issue1' } }] })
|
||||
end
|
||||
end
|
||||
|
||||
@@ -200,8 +200,8 @@ describe Integrations::Linear::ProcessorService do
|
||||
let(:error_response) { { error: 'Some error message' } }
|
||||
|
||||
it 'returns the error' do
|
||||
allow(linear_client).to receive(:linked_issue).with(url).and_return(error_response)
|
||||
result = service.linked_issue(url)
|
||||
allow(linear_client).to receive(:linked_issues).with(url).and_return(error_response)
|
||||
result = service.linked_issues(url)
|
||||
expect(result).to eq(error_response)
|
||||
end
|
||||
end
|
||||
|
||||
@@ -281,7 +281,7 @@ describe Linear do
|
||||
end
|
||||
|
||||
it 'returns linked issues' do
|
||||
response = linear_client.linked_issue('app.chatwoot.com')
|
||||
response = linear_client.linked_issues('app.chatwoot.com')
|
||||
expect(response).to eq({ 'linkedIssue' => { 'id' => 'issue1', 'title' => 'Title' } })
|
||||
end
|
||||
end
|
||||
@@ -294,7 +294,7 @@ describe Linear do
|
||||
end
|
||||
|
||||
it 'raises an exception' do
|
||||
response = linear_client.linked_issue('app.chatwoot.com')
|
||||
response = linear_client.linked_issues('app.chatwoot.com')
|
||||
expect(response).to eq({ :error => { 'errors' => [{ 'message' => 'Error retrieving data' }] }, :error_code => 422 })
|
||||
end
|
||||
end
|
||||
|
||||
Reference in New Issue
Block a user