From d509fe2edbe5281c2225be7c19449e83dc9816ba Mon Sep 17 00:00:00 2001 From: Paul Chavard Date: Fri, 18 Dec 2020 11:16:18 +0100 Subject: [PATCH 1/2] GraphQL: add has_fragment to context --- app/graphql/api/v2/context.rb | 30 ++++++++++++++++++++++++++++++ app/graphql/api/v2/schema.rb | 2 ++ 2 files changed, 32 insertions(+) create mode 100644 app/graphql/api/v2/context.rb diff --git a/app/graphql/api/v2/context.rb b/app/graphql/api/v2/context.rb new file mode 100644 index 000000000..227dee008 --- /dev/null +++ b/app/graphql/api/v2/context.rb @@ -0,0 +1,30 @@ +class Api::V2::Context < GraphQL::Query::Context + def has_fragment?(name) + if self["has_fragment_#{name}"] + true + else + visitor = HasFragment.new(self.query.selected_operation, name) + visitor.visit + self["has_fragment_#{name}"] = visitor.found + self["has_fragment_#{name}"] + end + end + + class HasFragment < GraphQL::Language::Visitor + def initialize(document, name) + super(document) + @name = name.to_s + @found = false + end + + attr_reader :found + + def on_inline_fragment(node, parent) + if node.type.name == @name + @found = true + end + + super + end + end +end diff --git a/app/graphql/api/v2/schema.rb b/app/graphql/api/v2/schema.rb index d734c00d7..1337a1ea3 100644 --- a/app/graphql/api/v2/schema.rb +++ b/app/graphql/api/v2/schema.rb @@ -6,6 +6,8 @@ class Api::V2::Schema < GraphQL::Schema query Types::QueryType mutation Types::MutationType + context_class Api::V2::Context + def self.id_from_object(object, type_definition, ctx) object.to_typed_id end From dc08993a8993ee26f7dee70f916ece473edaeb32 Mon Sep 17 00:00:00 2001 From: Paul Chavard Date: Fri, 18 Dec 2020 11:21:03 +0100 Subject: [PATCH 2/2] Add DateTime champ to GraphQL --- app/graphql/api/v2/schema.rb | 1 + app/graphql/schema.graphql | 28 +++++- app/graphql/types/champ_type.rb | 8 +- app/graphql/types/champs/date_champ_type.rb | 9 +- .../types/champs/datetime_champ_type.rb | 13 +++ .../api/v2/graphql_controller_spec.rb | 88 +++++++++++++++++++ 6 files changed, 144 insertions(+), 3 deletions(-) create mode 100644 app/graphql/types/champs/datetime_champ_type.rb diff --git a/app/graphql/api/v2/schema.rb b/app/graphql/api/v2/schema.rb index 1337a1ea3..a6fcb596a 100644 --- a/app/graphql/api/v2/schema.rb +++ b/app/graphql/api/v2/schema.rb @@ -43,6 +43,7 @@ class Api::V2::Schema < GraphQL::Schema Types::Champs::CheckboxChampType, Types::Champs::CiviliteChampType, Types::Champs::DateChampType, + Types::Champs::DatetimeChampType, Types::Champs::DecimalNumberChampType, Types::Champs::DossierLinkChampType, Types::Champs::IntegerNumberChampType, diff --git a/app/graphql/schema.graphql b/app/graphql/schema.graphql index 859d157ca..9cc94f5da 100644 --- a/app/graphql/schema.graphql +++ b/app/graphql/schema.graphql @@ -180,6 +180,33 @@ type CreateDirectUploadPayload { } type DateChamp implements Champ { + """ + La valeur du champ formaté en ISO8601 (Date). + """ + date: ISO8601Date + id: ID! + + """ + Libellé du champ. + """ + label: String! + + """ + La valeur du champ sous forme texte. + """ + stringValue: String + + """ + La valeur du champ formaté en ISO8601 (DateTime). + """ + value: ISO8601DateTime @deprecated(reason: "Utilisez le champ 'date' ou le fragment 'DatetimeChamp' à la place.") +} + +type DatetimeChamp implements Champ { + """ + La valeur du champ formaté en ISO8601 (DateTime). + """ + datetime: ISO8601DateTime id: ID! """ @@ -191,7 +218,6 @@ type DateChamp implements Champ { La valeur du champ sous forme texte. """ stringValue: String - value: ISO8601DateTime } type DecimalNumberChamp implements Champ { diff --git a/app/graphql/types/champ_type.rb b/app/graphql/types/champ_type.rb index e0cee2ea6..d9769a2c0 100644 --- a/app/graphql/types/champ_type.rb +++ b/app/graphql/types/champ_type.rb @@ -11,8 +11,14 @@ module Types case object when ::Champs::EngagementChamp, ::Champs::YesNoChamp, ::Champs::CheckboxChamp Types::Champs::CheckboxChampType - when ::Champs::DateChamp, ::Champs::DatetimeChamp + when ::Champs::DateChamp Types::Champs::DateChampType + when ::Champs::DatetimeChamp + if context.has_fragment?(:DatetimeChamp) + Types::Champs::DatetimeChampType + else + Types::Champs::DateChampType + end when ::Champs::DossierLinkChamp Types::Champs::DossierLinkChampType when ::Champs::PieceJustificativeChamp diff --git a/app/graphql/types/champs/date_champ_type.rb b/app/graphql/types/champs/date_champ_type.rb index 042de0546..d454c0621 100644 --- a/app/graphql/types/champs/date_champ_type.rb +++ b/app/graphql/types/champs/date_champ_type.rb @@ -2,12 +2,19 @@ module Types::Champs class DateChampType < Types::BaseObject implements Types::ChampType - field :value, GraphQL::Types::ISO8601DateTime, null: true + field :value, GraphQL::Types::ISO8601DateTime, "La valeur du champ formaté en ISO8601 (DateTime).", null: true, deprecation_reason: "Utilisez le champ 'date' ou le fragment 'DatetimeChamp' à la place." + field :date, GraphQL::Types::ISO8601Date, "La valeur du champ formaté en ISO8601 (Date).", null: true def value if object.value.present? Time.zone.parse(object.value) end end + + def date + if object.value.present? + Date.parse(object.value) + end + end end end diff --git a/app/graphql/types/champs/datetime_champ_type.rb b/app/graphql/types/champs/datetime_champ_type.rb new file mode 100644 index 000000000..a05bf1ca2 --- /dev/null +++ b/app/graphql/types/champs/datetime_champ_type.rb @@ -0,0 +1,13 @@ +module Types::Champs + class DatetimeChampType < Types::BaseObject + implements Types::ChampType + + field :datetime, GraphQL::Types::ISO8601DateTime, "La valeur du champ formaté en ISO8601 (DateTime).", null: true + + def datetime + if object.value.present? + Time.zone.parse(object.value) + end + end + end +end diff --git a/spec/controllers/api/v2/graphql_controller_spec.rb b/spec/controllers/api/v2/graphql_controller_spec.rb index 91a6b6f4e..9f964cf6c 100644 --- a/spec/controllers/api/v2/graphql_controller_spec.rb +++ b/spec/controllers/api/v2/graphql_controller_spec.rb @@ -409,6 +409,7 @@ describe API::V2::GraphqlController do } }" end + context "in the nominal case" do it "should be returned" do expect(gql_errors).to eq(nil) @@ -497,6 +498,93 @@ describe API::V2::GraphqlController do end end end + + context "champs" do + let(:procedure) { create(:procedure, :published, :for_individual, administrateurs: [admin], types_de_champ: [type_de_champ_date, type_de_champ_datetime]) } + let(:dossier) { create(:dossier, :en_construction, procedure: procedure) } + let(:type_de_champ_date) { build(:type_de_champ_date) } + let(:type_de_champ_datetime) { build(:type_de_champ_datetime) } + let(:champ_date) { dossier.champs.first } + let(:champ_datetime) { dossier.champs.second } + + before do + champ_date.update(value: '2019-07-10') + champ_datetime.update(value: '15/09/1962 15:35') + end + + context "with Date" do + let(:query) do + "{ + dossier(number: #{dossier.id}) { + champs { + id + label + ... on DateChamp { + value + } + } + } + }" + end + + it "should be returned" do + expect(gql_errors).to eq(nil) + expect(gql_data).to eq(dossier: { + champs: [ + { + id: champ_date.to_typed_id, + label: champ_date.libelle, + value: '2019-07-10T00:00:00+02:00' + }, + { + id: champ_datetime.to_typed_id, + label: champ_datetime.libelle, + value: '1962-09-15T15:35:00+01:00' + } + ] + }) + end + end + + context "with Datetime" do + let(:query) do + "{ + dossier(number: #{dossier.id}) { + champs { + id + label + ... on DateChamp { + value + date + } + ... on DatetimeChamp { + datetime + } + } + } + }" + end + + it "should be returned" do + expect(gql_errors).to eq(nil) + expect(gql_data).to eq(dossier: { + champs: [ + { + id: champ_date.to_typed_id, + label: champ_date.libelle, + value: '2019-07-10T00:00:00+02:00', + date: '2019-07-10' + }, + { + id: champ_datetime.to_typed_id, + label: champ_datetime.libelle, + datetime: '1962-09-15T15:35:00+01:00' + } + ] + }) + end + end + end end context "groupeInstructeur" do