diff --git a/app/graphql/mutations/files/create_label.rb b/app/graphql/mutations/files/create_label.rb new file mode 100644 index 00000000..3900b4fe --- /dev/null +++ b/app/graphql/mutations/files/create_label.rb @@ -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 diff --git a/app/graphql/mutations/files/label_file.rb b/app/graphql/mutations/files/label_file.rb new file mode 100644 index 00000000..1ed9089d --- /dev/null +++ b/app/graphql/mutations/files/label_file.rb @@ -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 diff --git a/app/graphql/root_operations/mutation.rb b/app/graphql/root_operations/mutation.rb index daf72f07..422456f8 100644 --- a/app/graphql/root_operations/mutation.rb +++ b/app/graphql/root_operations/mutation.rb @@ -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 diff --git a/app/graphql/root_operations/query.rb b/app/graphql/root_operations/query.rb index 4f944c08..8549e3fe 100644 --- a/app/graphql/root_operations/query.rb +++ b/app/graphql/root_operations/query.rb @@ -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 diff --git a/app/graphql/types/file.rb b/app/graphql/types/file.rb index d8219bbd..8b12e02c 100644 --- a/app/graphql/types/file.rb +++ b/app/graphql/types/file.rb @@ -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 diff --git a/app/graphql/types/label.rb b/app/graphql/types/label.rb new file mode 100644 index 00000000..3a92a106 --- /dev/null +++ b/app/graphql/types/label.rb @@ -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 diff --git a/spec/graphql/mutation/files/create_label_spec.rb b/spec/graphql/mutation/files/create_label_spec.rb new file mode 100644 index 00000000..5f0864f8 --- /dev/null +++ b/spec/graphql/mutation/files/create_label_spec.rb @@ -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 diff --git a/spec/graphql/mutation/files/label_file_spec.rb b/spec/graphql/mutation/files/label_file_spec.rb new file mode 100644 index 00000000..8a9a7779 --- /dev/null +++ b/spec/graphql/mutation/files/label_file_spec.rb @@ -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