Merge pull request #7503 from tchak/graphql-edit-blocks
fix(graphql): annotation edit mutation inside blocks
This commit is contained in:
commit
07acc0db94
13 changed files with 303 additions and 39 deletions
|
@ -7,8 +7,12 @@ module Mutations
|
||||||
field :annotation, Types::ChampType, null: true
|
field :annotation, Types::ChampType, null: true
|
||||||
field :errors, [Types::ValidationErrorType], null: true
|
field :errors, [Types::ValidationErrorType], null: true
|
||||||
|
|
||||||
def resolve_with_type(type, dossier, annotation_id, instructeur, value)
|
def resolve_with_type(dossier:, annotation_id:, instructeur:, value:)
|
||||||
annotation = find_annotation(dossier, type, annotation_id)
|
annotation = find_annotation(dossier, annotation_id)
|
||||||
|
|
||||||
|
if annotation.nil?
|
||||||
|
return { errors: ["L’annotation \"#{annotation_id}\" n’existe pas"] }
|
||||||
|
end
|
||||||
|
|
||||||
if block_given?
|
if block_given?
|
||||||
annotation.value = yield annotation.type_champ, value
|
annotation.value = yield annotation.type_champ, value
|
||||||
|
@ -31,18 +35,22 @@ module Mutations
|
||||||
|
|
||||||
private
|
private
|
||||||
|
|
||||||
def find_annotation(dossier, type, annotation_id)
|
def input_type
|
||||||
_, stable_id = GraphQL::Schema::UniqueWithinType.decode(annotation_id)
|
:text
|
||||||
dossier.champs_private
|
|
||||||
.joins(:type_de_champ)
|
|
||||||
.find_by!(types_de_champ: {
|
|
||||||
type_champ: annotation_type_champ(type),
|
|
||||||
stable_id: stable_id
|
|
||||||
})
|
|
||||||
end
|
end
|
||||||
|
|
||||||
def annotation_type_champ(type)
|
def find_annotation(dossier, annotation_id)
|
||||||
case type
|
stable_id, row = Champ.decode_typed_id(annotation_id)
|
||||||
|
|
||||||
|
Champ.joins(:type_de_champ).find_by(type_de_champ: {
|
||||||
|
type_champ: annotation_type_champ,
|
||||||
|
stable_id: stable_id,
|
||||||
|
private: true
|
||||||
|
}, private: true, row: row, dossier: dossier)
|
||||||
|
end
|
||||||
|
|
||||||
|
def annotation_type_champ
|
||||||
|
case input_type
|
||||||
when :text
|
when :text
|
||||||
[
|
[
|
||||||
TypeDeChamp.type_champs.fetch(:text),
|
TypeDeChamp.type_champs.fetch(:text),
|
||||||
|
|
|
@ -0,0 +1,38 @@
|
||||||
|
module Mutations
|
||||||
|
class DossierModifierAnnotationAjouterLigne < Mutations::BaseMutation
|
||||||
|
argument :dossier_id, ID, "Dossier ID", required: true, loads: Types::DossierType
|
||||||
|
argument :instructeur_id, ID, "Instructeur qui demande la modification.", required: true, loads: Types::ProfileType
|
||||||
|
argument :annotation_id, ID, "Annotation ID", required: true
|
||||||
|
|
||||||
|
field :annotation, Types::Champs::RepetitionChampType, null: true
|
||||||
|
field :errors, [Types::ValidationErrorType], null: true
|
||||||
|
|
||||||
|
def resolve(dossier:, annotation_id:, instructeur:)
|
||||||
|
annotation = find_annotation(dossier, annotation_id)
|
||||||
|
|
||||||
|
if annotation.nil?
|
||||||
|
return { errors: ["L’annotation \"#{annotation_id}\" n’existe pas"] }
|
||||||
|
end
|
||||||
|
|
||||||
|
annotation.add_row(dossier.revision)
|
||||||
|
|
||||||
|
{ annotation: annotation, errors: nil }
|
||||||
|
end
|
||||||
|
|
||||||
|
def authorized?(dossier:, instructeur:, **args)
|
||||||
|
dossier_authorized_for?(dossier, instructeur)
|
||||||
|
end
|
||||||
|
|
||||||
|
private
|
||||||
|
|
||||||
|
def find_annotation(dossier, annotation_id)
|
||||||
|
stable_id, row = Champ.decode_typed_id(annotation_id)
|
||||||
|
|
||||||
|
Champ.joins(:type_de_champ).find_by(type_de_champ: {
|
||||||
|
type_champ: TypeDeChamp.type_champs.fetch(:repetition),
|
||||||
|
stable_id: stable_id,
|
||||||
|
private: true
|
||||||
|
}, private: true, row: row, dossier: dossier)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
|
@ -6,11 +6,10 @@ module Mutations
|
||||||
|
|
||||||
def resolve(dossier:, annotation_id:, instructeur:, value:)
|
def resolve(dossier:, annotation_id:, instructeur:, value:)
|
||||||
resolve_with_type(
|
resolve_with_type(
|
||||||
:checkbox,
|
dossier: dossier,
|
||||||
dossier,
|
annotation_id: annotation_id,
|
||||||
annotation_id,
|
instructeur: instructeur,
|
||||||
instructeur,
|
value: value
|
||||||
value
|
|
||||||
) do |type_champ, value|
|
) do |type_champ, value|
|
||||||
if type_champ == TypeDeChamp.type_champs.fetch(:yes_no)
|
if type_champ == TypeDeChamp.type_champs.fetch(:yes_no)
|
||||||
value ? 'true' : 'false'
|
value ? 'true' : 'false'
|
||||||
|
@ -19,5 +18,11 @@ module Mutations
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
private
|
||||||
|
|
||||||
|
def input_type
|
||||||
|
:checkbox
|
||||||
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -6,12 +6,17 @@ module Mutations
|
||||||
|
|
||||||
def resolve(dossier:, annotation_id:, instructeur:, value:)
|
def resolve(dossier:, annotation_id:, instructeur:, value:)
|
||||||
resolve_with_type(
|
resolve_with_type(
|
||||||
:date,
|
dossier: dossier,
|
||||||
dossier,
|
annotation_id: annotation_id,
|
||||||
annotation_id,
|
instructeur: instructeur,
|
||||||
instructeur,
|
value: value
|
||||||
value
|
|
||||||
)
|
)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
private
|
||||||
|
|
||||||
|
def input_type
|
||||||
|
:date
|
||||||
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -6,12 +6,17 @@ module Mutations
|
||||||
|
|
||||||
def resolve(dossier:, annotation_id:, instructeur:, value:)
|
def resolve(dossier:, annotation_id:, instructeur:, value:)
|
||||||
resolve_with_type(
|
resolve_with_type(
|
||||||
:datetime,
|
dossier: dossier,
|
||||||
dossier,
|
annotation_id: annotation_id,
|
||||||
annotation_id,
|
instructeur: instructeur,
|
||||||
instructeur,
|
value: value
|
||||||
value
|
|
||||||
)
|
)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
private
|
||||||
|
|
||||||
|
def input_type
|
||||||
|
:datetime
|
||||||
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -6,12 +6,17 @@ module Mutations
|
||||||
|
|
||||||
def resolve(dossier:, annotation_id:, instructeur:, value:)
|
def resolve(dossier:, annotation_id:, instructeur:, value:)
|
||||||
resolve_with_type(
|
resolve_with_type(
|
||||||
:integer_number,
|
dossier: dossier,
|
||||||
dossier,
|
annotation_id: annotation_id,
|
||||||
annotation_id,
|
instructeur: instructeur,
|
||||||
instructeur,
|
value: value
|
||||||
value
|
|
||||||
)
|
)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
private
|
||||||
|
|
||||||
|
def input_type
|
||||||
|
:integer_number
|
||||||
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -6,12 +6,17 @@ module Mutations
|
||||||
|
|
||||||
def resolve(dossier:, annotation_id:, instructeur:, value:)
|
def resolve(dossier:, annotation_id:, instructeur:, value:)
|
||||||
resolve_with_type(
|
resolve_with_type(
|
||||||
:text,
|
dossier: dossier,
|
||||||
dossier,
|
annotation_id: annotation_id,
|
||||||
annotation_id,
|
instructeur: instructeur,
|
||||||
instructeur,
|
value: value
|
||||||
value
|
|
||||||
)
|
)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
private
|
||||||
|
|
||||||
|
def input_type
|
||||||
|
:text
|
||||||
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -1026,6 +1026,44 @@ type DossierLinkChamp implements Champ {
|
||||||
stringValue: String
|
stringValue: String
|
||||||
}
|
}
|
||||||
|
|
||||||
|
"""
|
||||||
|
Autogenerated input type of DossierModifierAnnotationAjouterLigne
|
||||||
|
"""
|
||||||
|
input DossierModifierAnnotationAjouterLigneInput {
|
||||||
|
"""
|
||||||
|
Annotation ID
|
||||||
|
"""
|
||||||
|
annotationId: ID!
|
||||||
|
|
||||||
|
"""
|
||||||
|
A unique identifier for the client performing the mutation.
|
||||||
|
"""
|
||||||
|
clientMutationId: String
|
||||||
|
|
||||||
|
"""
|
||||||
|
Dossier ID
|
||||||
|
"""
|
||||||
|
dossierId: ID!
|
||||||
|
|
||||||
|
"""
|
||||||
|
Instructeur qui demande la modification.
|
||||||
|
"""
|
||||||
|
instructeurId: ID!
|
||||||
|
}
|
||||||
|
|
||||||
|
"""
|
||||||
|
Autogenerated return type of DossierModifierAnnotationAjouterLigne
|
||||||
|
"""
|
||||||
|
type DossierModifierAnnotationAjouterLignePayload {
|
||||||
|
annotation: RepetitionChamp
|
||||||
|
|
||||||
|
"""
|
||||||
|
A unique identifier for the client performing the mutation.
|
||||||
|
"""
|
||||||
|
clientMutationId: String
|
||||||
|
errors: [ValidationError!]
|
||||||
|
}
|
||||||
|
|
||||||
"""
|
"""
|
||||||
Autogenerated input type of DossierModifierAnnotationCheckbox
|
Autogenerated input type of DossierModifierAnnotationCheckbox
|
||||||
"""
|
"""
|
||||||
|
@ -1664,6 +1702,12 @@ type Mutation {
|
||||||
"""
|
"""
|
||||||
input: DossierEnvoyerMessageInput!
|
input: DossierEnvoyerMessageInput!
|
||||||
): DossierEnvoyerMessagePayload
|
): DossierEnvoyerMessagePayload
|
||||||
|
dossierModifierAnnotationAjouterLigne(
|
||||||
|
"""
|
||||||
|
Parameters for DossierModifierAnnotationAjouterLigne
|
||||||
|
"""
|
||||||
|
input: DossierModifierAnnotationAjouterLigneInput!
|
||||||
|
): DossierModifierAnnotationAjouterLignePayload
|
||||||
|
|
||||||
"""
|
"""
|
||||||
Modifier l’annotation au format oui/non.
|
Modifier l’annotation au format oui/non.
|
||||||
|
|
|
@ -17,5 +17,6 @@ module Types
|
||||||
field :dossier_modifier_annotation_date, mutation: Mutations::DossierModifierAnnotationDate
|
field :dossier_modifier_annotation_date, mutation: Mutations::DossierModifierAnnotationDate
|
||||||
field :dossier_modifier_annotation_datetime, mutation: Mutations::DossierModifierAnnotationDatetime
|
field :dossier_modifier_annotation_datetime, mutation: Mutations::DossierModifierAnnotationDatetime
|
||||||
field :dossier_modifier_annotation_integer_number, mutation: Mutations::DossierModifierAnnotationIntegerNumber
|
field :dossier_modifier_annotation_integer_number, mutation: Mutations::DossierModifierAnnotationIntegerNumber
|
||||||
|
field :dossier_modifier_annotation_ajouter_ligne, mutation: Mutations::DossierModifierAnnotationAjouterLigne
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -126,7 +126,16 @@ class Champ < ApplicationRecord
|
||||||
end
|
end
|
||||||
|
|
||||||
def to_typed_id
|
def to_typed_id
|
||||||
type_de_champ.to_typed_id
|
if row.present?
|
||||||
|
GraphQL::Schema::UniqueWithinType.encode('Champ', "#{stable_id}|#{row}")
|
||||||
|
else
|
||||||
|
type_de_champ.to_typed_id
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
def self.decode_typed_id(typed_id)
|
||||||
|
_, stable_id_with_maybe_row = GraphQL::Schema::UniqueWithinType.decode(typed_id)
|
||||||
|
stable_id_with_maybe_row.split('|')
|
||||||
end
|
end
|
||||||
|
|
||||||
def html_label?
|
def html_label?
|
||||||
|
|
|
@ -224,6 +224,7 @@ FactoryBot.define do
|
||||||
type_de_champ_text = build(:type_de_champ_text,
|
type_de_champ_text = build(:type_de_champ_text,
|
||||||
procedure: champ_repetition.type_de_champ.procedure,
|
procedure: champ_repetition.type_de_champ.procedure,
|
||||||
position: 0,
|
position: 0,
|
||||||
|
private: champ_repetition.private?,
|
||||||
parent: parent,
|
parent: parent,
|
||||||
libelle: 'Nom')
|
libelle: 'Nom')
|
||||||
types_de_champ.push(type_de_champ_text)
|
types_de_champ.push(type_de_champ_text)
|
||||||
|
@ -234,6 +235,7 @@ FactoryBot.define do
|
||||||
type_de_champ_number = build(:type_de_champ_number,
|
type_de_champ_number = build(:type_de_champ_number,
|
||||||
procedure: champ_repetition.type_de_champ.procedure,
|
procedure: champ_repetition.type_de_champ.procedure,
|
||||||
position: 1,
|
position: 1,
|
||||||
|
private: champ_repetition.private?,
|
||||||
parent: parent,
|
parent: parent,
|
||||||
libelle: 'Age')
|
libelle: 'Age')
|
||||||
types_de_champ.push(type_de_champ_number)
|
types_de_champ.push(type_de_champ_number)
|
||||||
|
@ -241,7 +243,7 @@ FactoryBot.define do
|
||||||
|
|
||||||
evaluator.rows.times do |row|
|
evaluator.rows.times do |row|
|
||||||
champ_repetition.champs << types_de_champ.map do |type_de_champ|
|
champ_repetition.champs << types_de_champ.map do |type_de_champ|
|
||||||
build(:"champ_#{type_de_champ.type_champ}", dossier: champ_repetition.dossier, row: row, type_de_champ: type_de_champ, parent: champ_repetition)
|
build(:"champ_#{type_de_champ.type_champ}", dossier: champ_repetition.dossier, row: row, type_de_champ: type_de_champ, parent: champ_repetition, private: champ_repetition.private?)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -190,6 +190,12 @@ FactoryBot.define do
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
trait :with_private_repetition do
|
||||||
|
after(:build) do |procedure, _evaluator|
|
||||||
|
build(:type_de_champ_repetition, :private, procedure: procedure)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
trait :with_number do
|
trait :with_number do
|
||||||
after(:build) do |procedure, _evaluator|
|
after(:build) do |procedure, _evaluator|
|
||||||
build(:type_de_champ_number, procedure: procedure)
|
build(:type_de_champ_number, procedure: procedure)
|
||||||
|
|
131
spec/graphql/annotation_spec.rb
Normal file
131
spec/graphql/annotation_spec.rb
Normal file
|
@ -0,0 +1,131 @@
|
||||||
|
RSpec.describe Mutations::DossierModifierAnnotation, type: :graphql do
|
||||||
|
let(:admin) { create(:administrateur) }
|
||||||
|
let(:procedure) { create(:procedure, :published, :for_individual, :with_private_repetition, :with_type_de_champ_private, administrateurs: [admin]) }
|
||||||
|
let(:dossiers) { [] }
|
||||||
|
let(:instructeur) { create(:instructeur, followed_dossiers: dossiers) }
|
||||||
|
|
||||||
|
let(:query) { '' }
|
||||||
|
let(:context) { { administrateur_id: admin.id } }
|
||||||
|
let(:variables) { {} }
|
||||||
|
|
||||||
|
subject { API::V2::Schema.execute(query, variables: variables, context: context) }
|
||||||
|
|
||||||
|
let(:data) { subject['data'].deep_symbolize_keys }
|
||||||
|
let(:errors) { subject['errors'].deep_symbolize_keys }
|
||||||
|
|
||||||
|
before do
|
||||||
|
instructeur.assign_to_procedure(procedure)
|
||||||
|
end
|
||||||
|
|
||||||
|
describe 'dossierModifierAnnotationAjouterLigne' do
|
||||||
|
let(:dossier) { create(:dossier, :en_construction, :with_populated_annotations, procedure: procedure) }
|
||||||
|
let(:dossiers) { [dossier] }
|
||||||
|
|
||||||
|
let(:annotation) { dossier.champs_private.find(&:repetition?) }
|
||||||
|
let(:query) { DOSSIER_MODIFIER_ANNOTATION_AJOUTER_LIGNE_MUTATION }
|
||||||
|
let(:variables) do
|
||||||
|
{
|
||||||
|
input: {
|
||||||
|
dossierId: dossier.to_typed_id,
|
||||||
|
annotationId: annotation.to_typed_id,
|
||||||
|
instructeurId: instructeur.to_typed_id
|
||||||
|
}
|
||||||
|
}
|
||||||
|
end
|
||||||
|
|
||||||
|
context 'with invalid champ' do
|
||||||
|
let(:annotation) { dossier.champs_private.last }
|
||||||
|
|
||||||
|
it 'return error' do
|
||||||
|
expect(data).to eq(dossierModifierAnnotationAjouterLigne: {
|
||||||
|
annotation: nil,
|
||||||
|
errors: [{ message: "L’annotation \"#{annotation.to_typed_id}\" n’existe pas" }]
|
||||||
|
})
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
it 'add row' do
|
||||||
|
expect(annotation.champs.size).to eq(4)
|
||||||
|
expect(data).to eq(dossierModifierAnnotationAjouterLigne: {
|
||||||
|
annotation: {
|
||||||
|
id: annotation.to_typed_id
|
||||||
|
},
|
||||||
|
errors: nil
|
||||||
|
})
|
||||||
|
expect(annotation.reload.champs.size).to eq(6)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
describe 'dossierModifierAnnotationText' do
|
||||||
|
let(:dossier) { create(:dossier, :en_construction, :with_populated_annotations, procedure: procedure) }
|
||||||
|
let(:dossiers) { [dossier] }
|
||||||
|
|
||||||
|
let(:annotation) { dossier.champs_private.last }
|
||||||
|
let(:query) { DOSSIER_MODIFIER_ANNOTATION_TEXT_MUTATION }
|
||||||
|
let(:variables) do
|
||||||
|
{
|
||||||
|
input: {
|
||||||
|
dossierId: dossier.to_typed_id,
|
||||||
|
annotationId: annotation.to_typed_id,
|
||||||
|
instructeurId: instructeur.to_typed_id,
|
||||||
|
value: 'Hello world'
|
||||||
|
}
|
||||||
|
}
|
||||||
|
end
|
||||||
|
|
||||||
|
it 'update champ' do
|
||||||
|
expect(data).to eq(dossierModifierAnnotationText: {
|
||||||
|
annotation: {
|
||||||
|
id: annotation.to_typed_id
|
||||||
|
},
|
||||||
|
errors: nil
|
||||||
|
})
|
||||||
|
expect(annotation.reload.value).to eq('Hello world')
|
||||||
|
end
|
||||||
|
|
||||||
|
context 'with invalid champ' do
|
||||||
|
let(:annotation) { dossier.champs_private.find(&:repetition?) }
|
||||||
|
|
||||||
|
it 'return error' do
|
||||||
|
expect(data).to eq(dossierModifierAnnotationText: {
|
||||||
|
annotation: nil,
|
||||||
|
errors: [{ message: "L’annotation \"#{annotation.to_typed_id}\" n’existe pas" }]
|
||||||
|
})
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
context 'with rows' do
|
||||||
|
let(:annotation) { dossier.champs_private.find(&:repetition?).rows.first.first }
|
||||||
|
let(:other_annotation) { dossier.champs_private.find(&:repetition?).rows.second.first }
|
||||||
|
|
||||||
|
it 'update champ' do
|
||||||
|
expect(data).to eq(dossierModifierAnnotationText: {
|
||||||
|
annotation: {
|
||||||
|
id: annotation.to_typed_id
|
||||||
|
},
|
||||||
|
errors: nil
|
||||||
|
})
|
||||||
|
expect(annotation.reload.value).to eq('Hello world')
|
||||||
|
expect(other_annotation.reload.value).not_to eq('Hello world')
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
DOSSIER_MODIFIER_ANNOTATION_AJOUTER_LIGNE_MUTATION = <<-GRAPHQL
|
||||||
|
mutation($input: DossierModifierAnnotationAjouterLigneInput!) {
|
||||||
|
dossierModifierAnnotationAjouterLigne(input: $input) {
|
||||||
|
annotation { id }
|
||||||
|
errors { message }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
GRAPHQL
|
||||||
|
|
||||||
|
DOSSIER_MODIFIER_ANNOTATION_TEXT_MUTATION = <<-GRAPHQL
|
||||||
|
mutation($input: DossierModifierAnnotationTextInput!) {
|
||||||
|
dossierModifierAnnotationText(input: $input) {
|
||||||
|
annotation { id }
|
||||||
|
errors { message }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
GRAPHQL
|
||||||
|
end
|
Loading…
Reference in a new issue