From bb072ba9e93cfd892058a391f79d9bb2308c85ce Mon Sep 17 00:00:00 2001 From: Paul Chavard Date: Thu, 28 Jan 2021 13:53:01 +0100 Subject: [PATCH] Add id argument to most collections on dossier --- app/graphql/loaders/champ.rb | 27 +++++++++++++++ app/graphql/loaders/record.rb | 10 ++++-- app/graphql/schema.graphql | 8 ++--- app/graphql/types/dossier_type.rb | 56 ++++++++++++++++++++++++------- app/graphql/types/query_type.rb | 6 +++- app/models/application_record.rb | 4 +++ 6 files changed, 92 insertions(+), 19 deletions(-) create mode 100644 app/graphql/loaders/champ.rb diff --git a/app/graphql/loaders/champ.rb b/app/graphql/loaders/champ.rb new file mode 100644 index 000000000..b33672b10 --- /dev/null +++ b/app/graphql/loaders/champ.rb @@ -0,0 +1,27 @@ +# references: +# https://github.com/Shopify/graphql-batch/blob/master/examples/record_loader.rb + +module Loaders + class Champ < GraphQL::Batch::Loader + def initialize(dossier, private: false) + @where = { dossier: dossier, private: private } + end + + def load(key) + super(key.to_i) + end + + def perform(keys) + query(keys).each { |record| fulfill(record.stable_id, [record].compact) } + keys.each { |key| fulfill(key, nil) unless fulfilled?(key) } + end + + private + + def query(keys) + ::Champ.where(@where) + .includes(:type_de_champ) + .where(types_de_champ: { stable_id: keys }) + end + end +end diff --git a/app/graphql/loaders/record.rb b/app/graphql/loaders/record.rb index 9602a3b60..821a9f1cd 100644 --- a/app/graphql/loaders/record.rb +++ b/app/graphql/loaders/record.rb @@ -3,11 +3,13 @@ module Loaders class Record < GraphQL::Batch::Loader - def initialize(model, column: model.primary_key, where: nil) + def initialize(model, column: model.primary_key, where: nil, includes: nil, array: false) @model = model @column = column.to_s @column_type = model.type_for_attribute(@column) @where = where + @includes = includes + @array = array end def load(key) @@ -15,7 +17,10 @@ module Loaders end def perform(keys) - query(keys).each { |record| fulfill(record.public_send(@column), record) } + query(keys).each do |record| + fulfilled_value = @array ? [record].compact : record + fulfill(record.public_send(@column), fulfilled_value) + end keys.each { |key| fulfill(key, nil) unless fulfilled?(key) } end @@ -24,6 +29,7 @@ module Loaders def query(keys) scope = @model scope = scope.where(@where) if @where + scope = scope.includes(@includes) if @includes scope.where(@column => keys) end end diff --git a/app/graphql/schema.graphql b/app/graphql/schema.graphql index 6debefe95..215e6d2ff 100644 --- a/app/graphql/schema.graphql +++ b/app/graphql/schema.graphql @@ -508,15 +508,15 @@ type DirectUpload { Un dossier """ type Dossier { - annotations: [Champ!]! + annotations(id: ID): [Champ!]! archived: Boolean! """ L’URL de l’attestation au format PDF. """ attestation: File - avis: [Avis!]! - champs: [Champ!]! + avis(id: ID): [Avis!]! + champs(id: ID): [Champ!]! """ Date de la dernière modification. @@ -546,7 +546,7 @@ type Dossier { groupeInstructeur: GroupeInstructeur! id: ID! instructeurs: [Profile!]! - messages: [Message!]! + messages(id: ID): [Message!]! motivation: String motivationAttachment: File diff --git a/app/graphql/types/dossier_type.rb b/app/graphql/types/dossier_type.rb index b17ccb003..7eecf2b18 100644 --- a/app/graphql/types/dossier_type.rb +++ b/app/graphql/types/dossier_type.rb @@ -35,11 +35,19 @@ module Types field :demandeur, Types::DemandeurType, null: false field :instructeurs, [Types::ProfileType], null: false - field :messages, [Types::MessageType], null: false - field :avis, [Types::AvisType], null: false - field :champs, [Types::ChampType], null: false - field :annotations, [Types::ChampType], null: false + field :messages, [Types::MessageType], null: false do + argument :id, ID, required: false + end + field :avis, [Types::AvisType], null: false do + argument :id, ID, required: false + end + field :champs, [Types::ChampType], null: false do + argument :id, ID, required: false + end + field :annotations, [Types::ChampType], null: false do + argument :id, ID, required: false + end def state object.state @@ -69,20 +77,44 @@ module Types Loaders::Association.for(object.class, :followers_instructeurs).load(object) end - def messages - Loaders::Association.for(object.class, commentaires: [:instructeur, :user]).load(object) + def messages(id: nil) + if id.present? + Loaders::Record + .for(Commentaire, where: { dossier: object }, includes: [:instructeur, :user], array: true) + .load(ApplicationRecord.id_from_typed_id(id)) + else + Loaders::Association.for(object.class, commentaires: [:instructeur, :user]).load(object) + end end - def avis - Loaders::Association.for(object.class, avis: [:instructeur, :claimant]).load(object) + def avis(id: nil) + if id.present? + Loaders::Record + .for(Avis, where: { dossier: object }, includes: [:instructeur, :claimant], array: true) + .load(ApplicationRecord.id_from_typed_id(id)) + else + Loaders::Association.for(object.class, avis: [:instructeur, :claimant]).load(object) + end end - def champs - Loaders::Association.for(object.class, champs: [:type_de_champ]).load(object) + def champs(id: nil) + if id.present? + Loaders::Champ + .for(object, private: false) + .load(ApplicationRecord.id_from_typed_id(id)) + else + Loaders::Association.for(object.class, champs: :type_de_champ).load(object) + end end - def annotations - Loaders::Association.for(object.class, champs_private: [:type_de_champ]).load(object) + def annotations(id: nil) + if id.present? + Loaders::Champ + .for(object, private: true) + .load(ApplicationRecord.id_from_typed_id(id)) + else + Loaders::Association.for(object.class, champs_private: :type_de_champ).load(object) + end end def pdf diff --git a/app/graphql/types/query_type.rb b/app/graphql/types/query_type.rb index 34ba29f5b..cdcd2c56d 100644 --- a/app/graphql/types/query_type.rb +++ b/app/graphql/types/query_type.rb @@ -19,7 +19,11 @@ module Types end def dossier(number:) - Dossier.state_not_brouillon.for_api_v2.find(number) + if context.internal_use? + Dossier.state_not_brouillon.with_discarded.for_api_v2.find(number) + else + Dossier.state_not_brouillon.for_api_v2.find(number) + end rescue => e raise GraphQL::ExecutionError.new(e.message, extensions: { code: :not_found }) end diff --git a/app/models/application_record.rb b/app/models/application_record.rb index cece5f813..427e65704 100644 --- a/app/models/application_record.rb +++ b/app/models/application_record.rb @@ -13,6 +13,10 @@ class ApplicationRecord < ActiveRecord::Base raise ActiveRecord::RecordNotFound, e.message end + def self.id_from_typed_id(id) + GraphQL::Schema::UniqueWithinType.decode(id)[1] + end + def to_typed_id GraphQL::Schema::UniqueWithinType.encode(self.class.name, id) end