Skip to content

Commit

Permalink
GraphQL API for Labels (#1342)
Browse files Browse the repository at this point in the history
Related to #1119 

Example queries:

```GraphQL
query labels {
  labels {
    edges {
      node {
        id
        name
        color
        files {
          edges {
            node {
              id
            }
          }
        }
      }
    }
  }
}

mutation AttachLabel {
  labelFile(input: {fileId: "27", labelId: "1"}) {
    file {
      id
      labels {
        edges {
          node {
            id
          }
        }
      }
    }
  }
}

mutation CreateLabel {
  createLabel(input: {name: "PLA", color: "#111"}) {
    label {
      id
      name
      color
    }
  }
}

query file {
  file(id: "28") {
    labels {
      edges {
        node {
          id
          name
        }
      }
    }
  }
}
```
  • Loading branch information
sophiedeziel authored Mar 15, 2024
1 parent d77de99 commit 326548c
Show file tree
Hide file tree
Showing 8 changed files with 251 additions and 1 deletion.
24 changes: 24 additions & 0 deletions app/graphql/mutations/files/create_label.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
# frozen_string_literal: true

module Mutations
module Files
class CreateLabel < Base::Mutation
description 'Creates a label'

argument :name, String, required: true
argument :color, String, required: true

field :label, Types::Label, null: true

def resolve(name:, color:)
label = ::Label.new(name:, color:)

if label.save
{ label: }
else
{ label: nil }
end
end
end
end
end
27 changes: 27 additions & 0 deletions app/graphql/mutations/files/label_file.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
# frozen_string_literal: true

module Mutations
module Files
class LabelFile < Base::Mutation
description 'Attaches a label to a file'

argument :file_id, ID, required: true
argument :label_id, ID, required: true

field :label, Types::Label, null: true
field :file, Types::File, null: true

def resolve(file_id:, label_id:)
label = ::Label.find(label_id)
file = ::FileRecord.find(file_id)

file.labels << label if file.present? && label.present?

file.save!
{ label:, file: }
rescue StandardError
{ label:, file: }
end
end
end
end
2 changes: 2 additions & 0 deletions app/graphql/root_operations/mutation.rb
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,8 @@ class Mutation < Base::Object
field :uploadFile, mutation: Mutations::Files::UploadFile
field :updateFile, mutation: Mutations::Files::UpdateFile
field :updateFileNotes, mutation: Mutations::Files::UpdateFileNotes
field :createLabel, mutation: Mutations::Files::CreateLabel
field :labelFile, mutation: Mutations::Files::LabelFile

field :addPrinter, mutation: Mutations::Printers::AddPrinter
field :enqueueFiles, mutation: Mutations::Printers::EnqueueFiles
Expand Down
16 changes: 15 additions & 1 deletion app/graphql/root_operations/query.rb
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,21 @@ def files
argument :id, ID, required: true
end
def file(id:)
::FileRecord.find(id)
::FileRecord.find(id) if ::FileRecord.exists?(id)
end

field :labels, Types::Label.connection_type, null: false do
description 'labels'
end
def labels
::Label.all
end

field :label, Types::Label, null: true do
argument :id, ID, required: true
end
def label(id:)
::Label.find(id) if ::Label.exists?(id)
end

field :search_network_printers, [String], null: true
Expand Down
1 change: 1 addition & 0 deletions app/graphql/types/file.rb
Original file line number Diff line number Diff line change
Expand Up @@ -16,5 +16,6 @@ class File < Base::Object
field :top_file_comments, String, null: true
field :file_content, String, null: true
field :gcode_analysis, Types::GcodeAnalysis, null: true
field :labels, Label.connection_type, null: false
end
end
10 changes: 10 additions & 0 deletions app/graphql/types/label.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
# frozen_string_literal: true

module Types
class Label < Base::Object
field :id, ID, null: false
field :name, String, null: false
field :color, String, null: false
field :files, File.connection_type, method: :file_records, null: false
end
end
80 changes: 80 additions & 0 deletions spec/graphql/mutation/files/create_label_spec.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,80 @@
# frozen_string_literal: true

require 'rails_helper'

module Mutations
module Files
module CreateLabelSpec
include ActiveJob::TestHelper

RSpec.describe CreateLabel, type: :request do
let(:variables) do
{
input: {
name: 'PETG',
color: '#ff0000'
}
}
end

describe '.resolve' do
it 'creates a label' do
expect do
post '/graphql', params: { query:, variables: }
end.to change { Label.count }.by(1)
end

it 'returns the label' do
post '/graphql', params: { query:, variables: }
json = JSON.parse(response.body)
data = json['data']['createLabel']

expect(data['label']).to include(
'id' => be_present,
'name' => 'PETG',
'color' => '#ff0000'
)
end

context 'with invalid arguments' do
let(:variables) do
{
input: {
name: 'PETG',
color: 'blue'
}
}
end
it 'does not create a label' do
expect do
post '/graphql', params: { query:, variables: }
end.to change { Label.count }.by(0)
end

it 'returns a nil label' do
post '/graphql', params: { query:, variables: }
json = JSON.parse(response.body)
data = json['data']['createLabel']

expect(data['label']).to be_nil
end
end
end

def query
<<~GQL
mutation CreateLabel($input: CreateLabelInput!) {
createLabel(input: $input) {
label {
id
name
color
}
}
}
GQL
end
end
end
end
end
92 changes: 92 additions & 0 deletions spec/graphql/mutation/files/label_file_spec.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,92 @@
# frozen_string_literal: true

require 'rails_helper'

module Mutations
module Files
module LabelFileSpec
include ActiveJob::TestHelper

RSpec.describe LabelFile, type: :request do
let(:file) { create(:file_record) }
let(:label) { create(:label) }
let(:variables) do
{
input: {
fileId: file.id,
labelId: label.id
}
}
end

describe '.resolve' do
it 'attaches the label to the file' do
expect do
post '/graphql', params: { query:, variables: }
end.to change { file.labels.count }.by(1)
end

it 'returns the label and the file' do
post '/graphql', params: { query:, variables: }
json = JSON.parse(response.body)
data = json['data']['labelFile']

expect(data['label']).to include(
'id' => label.id.to_s
)
expect(data['file']).to include(
'id' => file.id.to_s
)
end

context 'with invalid arguments' do
let(:variables) do
{
input: {
fileId: file.id,
labelId: ''
}
}
end
it 'does not create a label' do
expect do
post '/graphql', params: { query:, variables: }
end.to change { file.labels.count }.by(0)
end

it 'returns a nil label' do
post '/graphql', params: { query:, variables: }
json = JSON.parse(response.body)
data = json['data']['labelFile']

expect(data['label']).to be_nil
end

it 'returns a nil file' do
post '/graphql', params: { query:, variables: }
json = JSON.parse(response.body)
data = json['data']['labelFile']

expect(data['file']).to be_nil
end
end
end

def query
<<~GQL
mutation LabelFile($input: LabelFileInput!) {
labelFile(input: $input) {
file {
id
}
label {
id
}
}
}
GQL
end
end
end
end
end

0 comments on commit 326548c

Please sign in to comment.