graphql 2.0.32 → 2.5.22

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (308) hide show
  1. checksums.yaml +4 -4
  2. data/lib/generators/graphql/detailed_trace_generator.rb +77 -0
  3. data/lib/generators/graphql/install/mutation_root_generator.rb +2 -2
  4. data/lib/generators/graphql/install/templates/base_mutation.erb +2 -0
  5. data/lib/generators/graphql/install/templates/mutation_type.erb +2 -0
  6. data/lib/generators/graphql/install_generator.rb +49 -0
  7. data/lib/generators/graphql/orm_mutations_base.rb +1 -1
  8. data/lib/generators/graphql/templates/base_argument.erb +2 -0
  9. data/lib/generators/graphql/templates/base_connection.erb +2 -0
  10. data/lib/generators/graphql/templates/base_edge.erb +2 -0
  11. data/lib/generators/graphql/templates/base_enum.erb +2 -0
  12. data/lib/generators/graphql/templates/base_field.erb +2 -0
  13. data/lib/generators/graphql/templates/base_input_object.erb +2 -0
  14. data/lib/generators/graphql/templates/base_interface.erb +2 -0
  15. data/lib/generators/graphql/templates/base_object.erb +2 -0
  16. data/lib/generators/graphql/templates/base_resolver.erb +8 -0
  17. data/lib/generators/graphql/templates/base_scalar.erb +2 -0
  18. data/lib/generators/graphql/templates/base_union.erb +2 -0
  19. data/lib/generators/graphql/templates/create_graphql_detailed_traces.erb +10 -0
  20. data/lib/generators/graphql/templates/graphql_controller.erb +2 -0
  21. data/lib/generators/graphql/templates/loader.erb +2 -0
  22. data/lib/generators/graphql/templates/mutation.erb +2 -0
  23. data/lib/generators/graphql/templates/node_type.erb +2 -0
  24. data/lib/generators/graphql/templates/query_type.erb +2 -0
  25. data/lib/generators/graphql/templates/schema.erb +5 -0
  26. data/lib/generators/graphql/type_generator.rb +1 -1
  27. data/lib/graphql/analysis/analyzer.rb +90 -0
  28. data/lib/graphql/analysis/field_usage.rb +82 -0
  29. data/lib/graphql/analysis/max_query_complexity.rb +20 -0
  30. data/lib/graphql/analysis/max_query_depth.rb +20 -0
  31. data/lib/graphql/analysis/query_complexity.rb +263 -0
  32. data/lib/graphql/analysis/query_depth.rb +58 -0
  33. data/lib/graphql/analysis/visitor.rb +280 -0
  34. data/lib/graphql/analysis.rb +95 -1
  35. data/lib/graphql/autoload.rb +38 -0
  36. data/lib/graphql/backtrace/table.rb +118 -55
  37. data/lib/graphql/backtrace.rb +1 -19
  38. data/lib/graphql/coercion_error.rb +1 -9
  39. data/lib/graphql/current.rb +57 -0
  40. data/lib/graphql/dashboard/application_controller.rb +41 -0
  41. data/lib/graphql/dashboard/detailed_traces.rb +47 -0
  42. data/lib/graphql/dashboard/installable.rb +22 -0
  43. data/lib/graphql/dashboard/landings_controller.rb +9 -0
  44. data/lib/graphql/dashboard/limiters.rb +93 -0
  45. data/lib/graphql/dashboard/operation_store.rb +199 -0
  46. data/lib/graphql/dashboard/statics/bootstrap-5.3.3.min.css +6 -0
  47. data/lib/graphql/dashboard/statics/bootstrap-5.3.3.min.js +7 -0
  48. data/lib/graphql/dashboard/statics/charts.min.css +1 -0
  49. data/lib/graphql/dashboard/statics/dashboard.css +30 -0
  50. data/lib/graphql/dashboard/statics/dashboard.js +143 -0
  51. data/lib/graphql/dashboard/statics/header-icon.png +0 -0
  52. data/lib/graphql/dashboard/statics/icon.png +0 -0
  53. data/lib/graphql/dashboard/statics_controller.rb +31 -0
  54. data/lib/graphql/dashboard/subscriptions.rb +97 -0
  55. data/lib/graphql/dashboard/views/graphql/dashboard/detailed_traces/traces/index.html.erb +45 -0
  56. data/lib/graphql/dashboard/views/graphql/dashboard/landings/show.html.erb +18 -0
  57. data/lib/graphql/dashboard/views/graphql/dashboard/limiters/limiters/show.html.erb +62 -0
  58. data/lib/graphql/dashboard/views/graphql/dashboard/not_installed.html.erb +18 -0
  59. data/lib/graphql/dashboard/views/graphql/dashboard/operation_store/clients/_form.html.erb +24 -0
  60. data/lib/graphql/dashboard/views/graphql/dashboard/operation_store/clients/edit.html.erb +21 -0
  61. data/lib/graphql/dashboard/views/graphql/dashboard/operation_store/clients/index.html.erb +69 -0
  62. data/lib/graphql/dashboard/views/graphql/dashboard/operation_store/clients/new.html.erb +7 -0
  63. data/lib/graphql/dashboard/views/graphql/dashboard/operation_store/index_entries/index.html.erb +39 -0
  64. data/lib/graphql/dashboard/views/graphql/dashboard/operation_store/index_entries/show.html.erb +32 -0
  65. data/lib/graphql/dashboard/views/graphql/dashboard/operation_store/operations/index.html.erb +81 -0
  66. data/lib/graphql/dashboard/views/graphql/dashboard/operation_store/operations/show.html.erb +71 -0
  67. data/lib/graphql/dashboard/views/graphql/dashboard/subscriptions/subscriptions/show.html.erb +41 -0
  68. data/lib/graphql/dashboard/views/graphql/dashboard/subscriptions/topics/index.html.erb +55 -0
  69. data/lib/graphql/dashboard/views/graphql/dashboard/subscriptions/topics/show.html.erb +40 -0
  70. data/lib/graphql/dashboard/views/layouts/graphql/dashboard/application.html.erb +108 -0
  71. data/lib/graphql/dashboard.rb +96 -0
  72. data/lib/graphql/dataloader/active_record_association_source.rb +84 -0
  73. data/lib/graphql/dataloader/active_record_source.rb +47 -0
  74. data/lib/graphql/dataloader/async_dataloader.rb +112 -0
  75. data/lib/graphql/dataloader/null_dataloader.rb +55 -10
  76. data/lib/graphql/dataloader/request.rb +5 -0
  77. data/lib/graphql/dataloader/source.rb +35 -12
  78. data/lib/graphql/dataloader.rb +224 -149
  79. data/lib/graphql/date_encoding_error.rb +1 -1
  80. data/lib/graphql/dig.rb +2 -1
  81. data/lib/graphql/duration_encoding_error.rb +16 -0
  82. data/lib/graphql/execution/interpreter/argument_value.rb +5 -1
  83. data/lib/graphql/execution/interpreter/arguments_cache.rb +5 -10
  84. data/lib/graphql/execution/interpreter/resolve.rb +23 -25
  85. data/lib/graphql/execution/interpreter/runtime/graphql_result.rb +228 -0
  86. data/lib/graphql/execution/interpreter/runtime.rb +363 -434
  87. data/lib/graphql/execution/interpreter.rb +91 -164
  88. data/lib/graphql/execution/lookahead.rb +105 -31
  89. data/lib/graphql/execution/multiplex.rb +7 -6
  90. data/lib/graphql/execution/next/field_resolve_step.rb +711 -0
  91. data/lib/graphql/execution/next/load_argument_step.rb +60 -0
  92. data/lib/graphql/execution/next/prepare_object_step.rb +129 -0
  93. data/lib/graphql/execution/next/runner.rb +389 -0
  94. data/lib/graphql/execution/next/selections_step.rb +37 -0
  95. data/lib/graphql/execution/next.rb +70 -0
  96. data/lib/graphql/execution.rb +1 -0
  97. data/lib/graphql/execution_error.rb +13 -10
  98. data/lib/graphql/introspection/directive_location_enum.rb +1 -1
  99. data/lib/graphql/introspection/directive_type.rb +7 -3
  100. data/lib/graphql/introspection/dynamic_fields.rb +5 -1
  101. data/lib/graphql/introspection/entry_points.rb +20 -6
  102. data/lib/graphql/introspection/enum_value_type.rb +5 -5
  103. data/lib/graphql/introspection/field_type.rb +13 -5
  104. data/lib/graphql/introspection/input_value_type.rb +21 -13
  105. data/lib/graphql/introspection/schema_type.rb +8 -11
  106. data/lib/graphql/introspection/type_type.rb +64 -28
  107. data/lib/graphql/invalid_name_error.rb +1 -1
  108. data/lib/graphql/invalid_null_error.rb +26 -17
  109. data/lib/graphql/language/block_string.rb +34 -18
  110. data/lib/graphql/language/cache.rb +13 -0
  111. data/lib/graphql/language/comment.rb +18 -0
  112. data/lib/graphql/language/definition_slice.rb +1 -1
  113. data/lib/graphql/language/document_from_schema_definition.rb +90 -61
  114. data/lib/graphql/language/lexer.rb +319 -193
  115. data/lib/graphql/language/nodes.rb +136 -77
  116. data/lib/graphql/language/parser.rb +807 -1985
  117. data/lib/graphql/language/printer.rb +324 -151
  118. data/lib/graphql/language/sanitized_printer.rb +21 -23
  119. data/lib/graphql/language/static_visitor.rb +171 -0
  120. data/lib/graphql/language/visitor.rb +23 -83
  121. data/lib/graphql/language.rb +71 -1
  122. data/lib/graphql/load_application_object_failed_error.rb +5 -1
  123. data/lib/graphql/pagination/array_connection.rb +6 -6
  124. data/lib/graphql/pagination/connection.rb +30 -1
  125. data/lib/graphql/pagination/connections.rb +32 -0
  126. data/lib/graphql/pagination/mongoid_relation_connection.rb +1 -2
  127. data/lib/graphql/query/context/scoped_context.rb +101 -0
  128. data/lib/graphql/query/context.rb +82 -144
  129. data/lib/graphql/query/null_context.rb +15 -18
  130. data/lib/graphql/query/partial.rb +179 -0
  131. data/lib/graphql/query/validation_pipeline.rb +4 -4
  132. data/lib/graphql/query/variable_validation_error.rb +1 -1
  133. data/lib/graphql/query/variables.rb +3 -3
  134. data/lib/graphql/query.rb +126 -81
  135. data/lib/graphql/railtie.rb +16 -6
  136. data/lib/graphql/rake_task.rb +3 -12
  137. data/lib/graphql/rubocop/graphql/base_cop.rb +1 -1
  138. data/lib/graphql/rubocop/graphql/field_type_in_block.rb +144 -0
  139. data/lib/graphql/rubocop/graphql/root_types_in_block.rb +38 -0
  140. data/lib/graphql/rubocop.rb +2 -0
  141. data/lib/graphql/schema/addition.rb +26 -13
  142. data/lib/graphql/schema/always_visible.rb +7 -2
  143. data/lib/graphql/schema/argument.rb +75 -9
  144. data/lib/graphql/schema/base_64_encoder.rb +3 -5
  145. data/lib/graphql/schema/build_from_definition.rb +123 -60
  146. data/lib/graphql/schema/directive/flagged.rb +4 -2
  147. data/lib/graphql/schema/directive/one_of.rb +12 -0
  148. data/lib/graphql/schema/directive/specified_by.rb +14 -0
  149. data/lib/graphql/schema/directive.rb +54 -2
  150. data/lib/graphql/schema/enum.rb +110 -27
  151. data/lib/graphql/schema/enum_value.rb +10 -2
  152. data/lib/graphql/schema/field/connection_extension.rb +15 -49
  153. data/lib/graphql/schema/field/scope_extension.rb +23 -7
  154. data/lib/graphql/schema/field.rb +245 -118
  155. data/lib/graphql/schema/field_extension.rb +34 -1
  156. data/lib/graphql/schema/has_single_input_argument.rb +160 -0
  157. data/lib/graphql/schema/input_object.rb +116 -60
  158. data/lib/graphql/schema/interface.rb +34 -16
  159. data/lib/graphql/schema/introspection_system.rb +8 -17
  160. data/lib/graphql/schema/late_bound_type.rb +4 -0
  161. data/lib/graphql/schema/list.rb +3 -3
  162. data/lib/graphql/schema/loader.rb +3 -4
  163. data/lib/graphql/schema/member/base_dsl_methods.rb +18 -2
  164. data/lib/graphql/schema/member/has_arguments.rb +132 -100
  165. data/lib/graphql/schema/member/has_authorization.rb +35 -0
  166. data/lib/graphql/schema/member/has_dataloader.rb +99 -0
  167. data/lib/graphql/schema/member/has_deprecation_reason.rb +15 -0
  168. data/lib/graphql/schema/member/has_directives.rb +4 -4
  169. data/lib/graphql/schema/member/has_fields.rb +115 -15
  170. data/lib/graphql/schema/member/has_interfaces.rb +26 -12
  171. data/lib/graphql/schema/member/has_unresolved_type_error.rb +5 -1
  172. data/lib/graphql/schema/member/has_validators.rb +1 -1
  173. data/lib/graphql/schema/member/relay_shortcuts.rb +1 -1
  174. data/lib/graphql/schema/member/scoped.rb +19 -0
  175. data/lib/graphql/schema/member/type_system_helpers.rb +17 -4
  176. data/lib/graphql/schema/member/validates_input.rb +3 -3
  177. data/lib/graphql/schema/member.rb +6 -0
  178. data/lib/graphql/schema/mutation.rb +7 -0
  179. data/lib/graphql/schema/object.rb +34 -8
  180. data/lib/graphql/schema/printer.rb +9 -7
  181. data/lib/graphql/schema/ractor_shareable.rb +79 -0
  182. data/lib/graphql/schema/relay_classic_mutation.rb +6 -129
  183. data/lib/graphql/schema/resolver.rb +90 -32
  184. data/lib/graphql/schema/scalar.rb +4 -9
  185. data/lib/graphql/schema/subscription.rb +63 -10
  186. data/lib/graphql/schema/timeout.rb +19 -2
  187. data/lib/graphql/schema/type_expression.rb +2 -2
  188. data/lib/graphql/schema/union.rb +2 -2
  189. data/lib/graphql/schema/unique_within_type.rb +1 -1
  190. data/lib/graphql/schema/validator/all_validator.rb +62 -0
  191. data/lib/graphql/schema/validator/required_validator.rb +92 -11
  192. data/lib/graphql/schema/validator.rb +3 -1
  193. data/lib/graphql/schema/visibility/migration.rb +188 -0
  194. data/lib/graphql/schema/visibility/profile.rb +445 -0
  195. data/lib/graphql/schema/visibility/visit.rb +190 -0
  196. data/lib/graphql/schema/visibility.rb +311 -0
  197. data/lib/graphql/schema/warden.rb +275 -103
  198. data/lib/graphql/schema.rb +950 -210
  199. data/lib/graphql/static_validation/all_rules.rb +3 -3
  200. data/lib/graphql/static_validation/base_visitor.rb +7 -6
  201. data/lib/graphql/static_validation/literal_validator.rb +6 -7
  202. data/lib/graphql/static_validation/rules/argument_literals_are_compatible.rb +1 -1
  203. data/lib/graphql/static_validation/rules/argument_names_are_unique.rb +1 -1
  204. data/lib/graphql/static_validation/rules/arguments_are_defined.rb +3 -2
  205. data/lib/graphql/static_validation/rules/directives_are_defined.rb +3 -3
  206. data/lib/graphql/static_validation/rules/directives_are_in_valid_locations.rb +2 -0
  207. data/lib/graphql/static_validation/rules/fields_are_defined_on_type.rb +12 -2
  208. data/lib/graphql/static_validation/rules/fields_have_appropriate_selections.rb +47 -13
  209. data/lib/graphql/static_validation/rules/fields_will_merge.rb +88 -25
  210. data/lib/graphql/static_validation/rules/fields_will_merge_error.rb +10 -2
  211. data/lib/graphql/static_validation/rules/fragment_spreads_are_possible.rb +3 -3
  212. data/lib/graphql/static_validation/rules/fragment_types_exist.rb +12 -2
  213. data/lib/graphql/static_validation/rules/fragments_are_on_composite_types.rb +1 -1
  214. data/lib/graphql/static_validation/rules/mutation_root_exists.rb +1 -1
  215. data/lib/graphql/static_validation/rules/no_definitions_are_present.rb +1 -1
  216. data/lib/graphql/static_validation/rules/not_single_subscription_error.rb +25 -0
  217. data/lib/graphql/static_validation/rules/query_root_exists.rb +1 -1
  218. data/lib/graphql/static_validation/rules/required_arguments_are_present.rb +5 -5
  219. data/lib/graphql/static_validation/rules/required_input_object_attributes_are_present.rb +5 -5
  220. data/lib/graphql/static_validation/rules/subscription_root_exists_and_single_subscription_selection.rb +26 -0
  221. data/lib/graphql/static_validation/rules/unique_directives_per_location.rb +7 -3
  222. data/lib/graphql/static_validation/rules/variable_default_values_are_correctly_typed.rb +18 -27
  223. data/lib/graphql/static_validation/rules/variable_names_are_unique.rb +1 -1
  224. data/lib/graphql/static_validation/rules/variable_usages_are_allowed.rb +2 -2
  225. data/lib/graphql/static_validation/rules/variables_are_input_types.rb +11 -2
  226. data/lib/graphql/static_validation/validation_context.rb +21 -5
  227. data/lib/graphql/static_validation/validator.rb +9 -1
  228. data/lib/graphql/static_validation.rb +0 -1
  229. data/lib/graphql/subscriptions/action_cable_subscriptions.rb +8 -5
  230. data/lib/graphql/subscriptions/broadcast_analyzer.rb +11 -5
  231. data/lib/graphql/subscriptions/default_subscription_resolve_extension.rb +12 -10
  232. data/lib/graphql/subscriptions/event.rb +21 -4
  233. data/lib/graphql/subscriptions/serialize.rb +3 -1
  234. data/lib/graphql/subscriptions.rb +21 -17
  235. data/lib/graphql/testing/helpers.rb +161 -0
  236. data/lib/graphql/testing/mock_action_cable.rb +111 -0
  237. data/lib/graphql/testing.rb +3 -0
  238. data/lib/graphql/tracing/active_support_notifications_trace.rb +14 -3
  239. data/lib/graphql/tracing/active_support_notifications_tracing.rb +1 -1
  240. data/lib/graphql/tracing/appoptics_trace.rb +7 -3
  241. data/lib/graphql/tracing/appoptics_tracing.rb +9 -2
  242. data/lib/graphql/tracing/appsignal_trace.rb +32 -59
  243. data/lib/graphql/tracing/appsignal_tracing.rb +2 -0
  244. data/lib/graphql/tracing/call_legacy_tracers.rb +66 -0
  245. data/lib/graphql/tracing/data_dog_trace.rb +46 -162
  246. data/lib/graphql/tracing/data_dog_tracing.rb +2 -0
  247. data/lib/graphql/tracing/detailed_trace/active_record_backend.rb +74 -0
  248. data/lib/graphql/tracing/detailed_trace/memory_backend.rb +60 -0
  249. data/lib/graphql/tracing/detailed_trace/redis_backend.rb +72 -0
  250. data/lib/graphql/tracing/detailed_trace.rb +156 -0
  251. data/lib/graphql/tracing/legacy_hooks_trace.rb +75 -0
  252. data/lib/graphql/tracing/legacy_trace.rb +4 -61
  253. data/lib/graphql/tracing/monitor_trace.rb +283 -0
  254. data/lib/graphql/tracing/new_relic_trace.rb +47 -54
  255. data/lib/graphql/tracing/new_relic_tracing.rb +2 -0
  256. data/lib/graphql/tracing/notifications_trace.rb +183 -37
  257. data/lib/graphql/tracing/notifications_tracing.rb +2 -0
  258. data/lib/graphql/tracing/null_trace.rb +9 -0
  259. data/lib/graphql/tracing/perfetto_trace/trace.proto +141 -0
  260. data/lib/graphql/tracing/perfetto_trace/trace_pb.rb +33 -0
  261. data/lib/graphql/tracing/perfetto_trace.rb +864 -0
  262. data/lib/graphql/tracing/platform_tracing.rb +3 -1
  263. data/lib/graphql/tracing/{prometheus_tracing → prometheus_trace}/graphql_collector.rb +5 -1
  264. data/lib/graphql/tracing/prometheus_trace.rb +73 -73
  265. data/lib/graphql/tracing/prometheus_tracing.rb +2 -0
  266. data/lib/graphql/tracing/scout_trace.rb +32 -58
  267. data/lib/graphql/tracing/scout_tracing.rb +2 -0
  268. data/lib/graphql/tracing/sentry_trace.rb +82 -0
  269. data/lib/graphql/tracing/statsd_trace.rb +33 -45
  270. data/lib/graphql/tracing/statsd_tracing.rb +2 -0
  271. data/lib/graphql/tracing/trace.rb +112 -1
  272. data/lib/graphql/tracing.rb +31 -28
  273. data/lib/graphql/type_kinds.rb +2 -1
  274. data/lib/graphql/types/iso_8601_duration.rb +77 -0
  275. data/lib/graphql/types/relay/connection_behaviors.rb +44 -2
  276. data/lib/graphql/types/relay/edge_behaviors.rb +18 -0
  277. data/lib/graphql/types/relay/has_node_field.rb +13 -8
  278. data/lib/graphql/types/relay/has_nodes_field.rb +13 -8
  279. data/lib/graphql/types/relay/node_behaviors.rb +13 -2
  280. data/lib/graphql/types/relay/page_info_behaviors.rb +4 -0
  281. data/lib/graphql/types.rb +18 -10
  282. data/lib/graphql/unauthorized_enum_value_error.rb +13 -0
  283. data/lib/graphql/unauthorized_error.rb +5 -1
  284. data/lib/graphql/version.rb +1 -1
  285. data/lib/graphql.rb +71 -54
  286. data/readme.md +12 -2
  287. metadata +233 -37
  288. data/lib/graphql/analysis/ast/analyzer.rb +0 -84
  289. data/lib/graphql/analysis/ast/field_usage.rb +0 -57
  290. data/lib/graphql/analysis/ast/max_query_complexity.rb +0 -22
  291. data/lib/graphql/analysis/ast/max_query_depth.rb +0 -22
  292. data/lib/graphql/analysis/ast/query_complexity.rb +0 -230
  293. data/lib/graphql/analysis/ast/query_depth.rb +0 -55
  294. data/lib/graphql/analysis/ast/visitor.rb +0 -276
  295. data/lib/graphql/analysis/ast.rb +0 -81
  296. data/lib/graphql/backtrace/inspect_result.rb +0 -50
  297. data/lib/graphql/backtrace/trace.rb +0 -96
  298. data/lib/graphql/backtrace/tracer.rb +0 -80
  299. data/lib/graphql/deprecation.rb +0 -9
  300. data/lib/graphql/filter.rb +0 -59
  301. data/lib/graphql/language/parser.y +0 -560
  302. data/lib/graphql/language/token.rb +0 -34
  303. data/lib/graphql/schema/base_64_bp.rb +0 -26
  304. data/lib/graphql/schema/invalid_type_error.rb +0 -7
  305. data/lib/graphql/schema/null_mask.rb +0 -11
  306. data/lib/graphql/static_validation/rules/subscription_root_exists.rb +0 -17
  307. data/lib/graphql/static_validation/type_stack.rb +0 -216
  308. data/lib/graphql/subscriptions/instrumentation.rb +0 -28
@@ -0,0 +1,97 @@
1
+ # frozen_string_literal: true
2
+ require_relative "./installable"
3
+ module Graphql
4
+ class Dashboard < Rails::Engine
5
+ module Subscriptions
6
+ class BaseController < Graphql::Dashboard::ApplicationController
7
+ include Installable
8
+
9
+ def feature_installed?
10
+ defined?(GraphQL::Pro::Subscriptions) && schema_class.subscriptions.is_a?(GraphQL::Pro::Subscriptions)
11
+ end
12
+
13
+ INSTALLABLE_COMPONENT_HEADER_HTML = "GraphQL-Pro Subscriptions aren't installed on this schema yet.".html_safe
14
+ INSTALLABLE_COMPONENT_MESSAGE_HTML = <<-HTML.html_safe
15
+ Deliver live updates over
16
+ <a href="https://graphql-ruby.org/subscriptions/pusher_implementation.html">Pusher</a> or
17
+ <a href="https://graphql-ruby.org/subscriptions/ably_implementation.html"> Ably</a>
18
+ with GraphQL-Pro's subscription integrations.
19
+ HTML
20
+ end
21
+
22
+ class TopicsController < BaseController
23
+ def show
24
+ topic_name = params[:name]
25
+ all_subscription_ids = []
26
+ schema_class.subscriptions.each_subscription_id(topic_name) do |sid|
27
+ all_subscription_ids << sid
28
+ end
29
+
30
+ page = params[:page]&.to_i || 1
31
+ limit = params[:per_page]&.to_i || 20
32
+ offset = limit * (page - 1)
33
+ subscription_ids = all_subscription_ids[offset, limit]
34
+ subs = schema_class.subscriptions.read_subscriptions(subscription_ids)
35
+ show_broadcast_subscribers_count = schema_class.subscriptions.show_broadcast_subscribers_count?
36
+ subs.each do |sub|
37
+ sub[:is_broadcast] = is_broadcast = schema_class.subscriptions.broadcast_subscription_id?(sub[:id])
38
+ if is_broadcast && show_broadcast_subscribers_count
39
+ sub[:subscribers_count] = sub_count =schema_class.subscriptions.count_broadcast_subscribed(sub[:id])
40
+ sub[:still_subscribed] = sub_count > 0
41
+ else
42
+ sub[:still_subscribed] = schema_class.subscriptions.still_subscribed?(sub[:id])
43
+ sub[:subscribers_count] = nil
44
+ end
45
+ end
46
+
47
+ @topic_last_triggered_at = schema_class.subscriptions.topic_last_triggered_at(topic_name)
48
+ @subscriptions = subs
49
+ @subscriptions_count = all_subscription_ids.size
50
+ @show_broadcast_subscribers_count = show_broadcast_subscribers_count
51
+ @has_next_page = all_subscription_ids.size > offset + limit ? page + 1 : false
52
+ end
53
+
54
+ def index
55
+ page = params[:page]&.to_i || 1
56
+ per_page = params[:per_page]&.to_i || 20
57
+ offset = per_page * (page - 1)
58
+ limit = per_page
59
+ topics, all_topics_count, has_next_page = schema_class.subscriptions.topics(offset: offset, limit: limit)
60
+
61
+ @topics = topics
62
+ @all_topics_count = all_topics_count
63
+ @has_next_page = has_next_page
64
+ @page = page
65
+ end
66
+ end
67
+
68
+ class SubscriptionsController < BaseController
69
+ def show
70
+ subscription_id = params[:id]
71
+ subscriptions = schema_class.subscriptions
72
+ query_data = subscriptions.read_subscription(subscription_id)
73
+ is_broadcast = subscriptions.broadcast_subscription_id?(subscription_id)
74
+
75
+ if is_broadcast && subscriptions.show_broadcast_subscribers_count?
76
+ subscribers_count = subscriptions.count_broadcast_subscribed(subscription_id)
77
+ is_still_subscribed = subscribers_count > 0
78
+ else
79
+ subscribers_count = nil
80
+ is_still_subscribed = subscriptions.still_subscribed?(subscription_id)
81
+ end
82
+
83
+ @query_data = query_data
84
+ @still_subscribed = is_still_subscribed
85
+ @is_broadcast = is_broadcast
86
+ @subscribers_count = subscribers_count
87
+ end
88
+
89
+ def clear_all
90
+ schema_class.subscriptions.clear
91
+ flash[:success] = "All subscription data cleared."
92
+ head :no_content
93
+ end
94
+ end
95
+ end
96
+ end
97
+ end
@@ -0,0 +1,45 @@
1
+ <% content_for(:title, "Profiles") %>
2
+ <div class="row justify-content-between mt-3">
3
+ <div class="col-auto">
4
+ <h3>Detailed Profiles</h3>
5
+ </div>
6
+ <div class="col-auto">
7
+ <%= button_tag "Delete All Traces", class: "btn btn-sm btn-outline-danger", data: { perfetto_delete_all: graphql_dashboard.delete_all_detailed_traces_traces_path } %>
8
+ </div>
9
+ </div>
10
+
11
+ <div class="row">
12
+ <div class="col">
13
+ <table class="table table-striped">
14
+ <thead>
15
+ <tr>
16
+ <th>Operation</th>
17
+ <th>Duration (ms) </th>
18
+ <th>Timestamp</th>
19
+ <th>Open in Perfetto UI</th>
20
+ </tr>
21
+ </thead>
22
+ <tbody>
23
+ <% if @traces.empty? %>
24
+ <tr>
25
+ <td colspan="4" class="text-center">
26
+ <em>No traces saved yet. Read about saving traces <%= link_to "in the docs", "https://graphql-ruby.org/queries/tracing#detailed-profiles" %>.</em>
27
+ </td>
28
+ </tr>
29
+ <% end %>
30
+ <% @traces.each do |trace| %>
31
+ <tr>
32
+ <td><%= trace.operation_name %></td>
33
+ <td><%= trace.duration_ms.round(2) %></td>
34
+ <td><%= Time.at(trace.begin_ms / 1000.0).strftime("%Y-%m-%d %H:%M:%S.%L") %></td>
35
+ <td><%= link_to "View ↗", "#", data: { perfetto_open: trace.operation_name, perfetto_path: graphql_dashboard.detailed_traces_trace_path(trace.id) } %></td>
36
+ <td><%= link_to "Delete", "#", data: { perfetto_delete: graphql_dashboard.detailed_traces_trace_path(trace.id) }, class: "text-danger" %></td>
37
+ </tr>
38
+ <% end %>
39
+ </tbody>
40
+ </table>
41
+ <% if @last && @traces.size >= @last %>
42
+ <%= link_to("Previous >", graphql_dashboard.detailed_traces_traces_path(last: @last, before: @traces.last.begin_ms), class: "btn btn-outline-primary") %>
43
+ <% end %>
44
+ </div>
45
+ </div>
@@ -0,0 +1,18 @@
1
+ <% content_for(:title, "Landing") %>
2
+
3
+ <div class="row">
4
+ <div class="col-md col-lg-8 mx-auto pt-4">
5
+ <div class="card mt-4">
6
+ <div class="card-body">
7
+ <div class="card-title">
8
+ <h2>
9
+ Welcome to the GraphQL-Ruby Dashboard
10
+ </h2>
11
+ </div>
12
+ <p class="card-text">
13
+ Click the links above to see data about your schema (<code><%= schema_class %></code>).
14
+ </p>
15
+ </div>
16
+ </div>
17
+ </div>
18
+ </div>
@@ -0,0 +1,62 @@
1
+ <% content_for(:title, @title) %>
2
+ <% if @install_path %>
3
+ <div class="row mt-3">
4
+ <div class="col">
5
+ <h3><%= @title %></h3>
6
+ <p>It looks like this limiter isn't installed yet. <a href="<%= @install_path %>">Install it now</a>.</p>
7
+ </div>
8
+ </div>
9
+ <% else %>
10
+ <div class="row mt-3 justify-content-between">
11
+ <div class="col-auto">
12
+ <h3><%= @title %></h3>
13
+ </div>
14
+ <div class="col-auto">
15
+ <div class="btn-group">
16
+ <%= link_to("This Hour", graphql_dashboard.limiters_limiter_path(params[:name], chart: "hour"), class: "btn btn-sm btn-outline-primary #{@chart_mode == "hour" ? "active" : "inactive"}", params: { chart: "hour" }) %>
17
+ <%= link_to("Today", graphql_dashboard.limiters_limiter_path(params[:name], chart: "day"), class: "btn btn-sm btn-outline-primary #{@chart_mode == "day" ? "active" : "inactive"}", params: { chart: "day" }) %>
18
+ <%= link_to("This Month", graphql_dashboard.limiters_limiter_path(params[:name], chart: "month"), class: "btn btn-sm btn-outline-primary #{@chart_mode == "month" ? "active" : "inactive"}", params: { chart: "month" }) %>
19
+ </div>
20
+ </div>
21
+ <div class="col-auto">
22
+ <%= form_tag graphql_dashboard.limiters_limiter_path(params[:name], chart: @chart_mode), method: "patch" do %>
23
+ <%= submit_tag "#{@current_soft ? "Disable" : "Enable"} Soft Limiting", class: "btn btn-sm btn-outline-warning" %>
24
+ <% end %>
25
+ </div>
26
+ </div>
27
+
28
+ <div class="row">
29
+ <div class="col ms-4">
30
+ <div id="limiter-histogram">
31
+ <table class="charts-css column multiple stacked show-labels hide-data show-primary-axis">
32
+ <thead>
33
+ <th>Date</th>
34
+ <th scope="col">Limited Requests</th>
35
+ <th scope="col">Unlimited Requests</th>
36
+ </thead>
37
+ <tbody>
38
+ <% @histogram.columns.each_with_index do |col, col_idx| %>
39
+ <tr>
40
+ <th scope="row" class="text-end"><%= col.label %></th>
41
+ <% col.values.each_with_index do |value, val_idx| %>
42
+ <td id="data-<%= col_idx %>-<%= val_idx %>">
43
+ <span class="data"><%= value.formatted_value %></span>
44
+ <span class="tooltip"><%= value.label %>: <%= value.formatted_value %><br><%= col.label %></span>
45
+ </td>
46
+ <% end %>
47
+ </tr>
48
+ <% end %>
49
+ </tbody>
50
+ </table>
51
+ </div>
52
+ </div>
53
+ </div>
54
+ <%= content_tag "style", nonce: @csp_nonce do %>
55
+ <% @histogram.columns.each_with_index do |col, col_idx| %>
56
+ <% col_max = @histogram.max_column_value.to_f %>
57
+ <% col.values.each_with_index do |val, val_idx| %>
58
+ #data-<%= col_idx %>-<%= val_idx %> { --size: <%= val.value / col_max %>}
59
+ <% end %>
60
+ <% end %>
61
+ <% end %>
62
+ <% end %>
@@ -0,0 +1,18 @@
1
+ <% content_for(:title, "Operation Store") %>
2
+
3
+ <div class="row">
4
+ <div class="col-md col-lg-8 mx-auto pt-4">
5
+ <div class="card mt-4">
6
+ <div class="card-body">
7
+ <div class="card-title">
8
+ <h2>
9
+ <%= @component_header_html %>
10
+ </h2>
11
+ </div>
12
+ <p class="card-text">
13
+ <%= @component_message_html %>
14
+ </p>
15
+ </div>
16
+ </div>
17
+ </div>
18
+ </div>
@@ -0,0 +1,24 @@
1
+ <%= form_tag((@client.persisted? ? graphql_dashboard.operation_store_client_path(name: @client.name) : graphql_dashboard.operation_store_clients_path), method: (@client.persisted? ? "patch" : "post")) do %>
2
+ <div class="row">
3
+ <label class="col-2 col-form-label">Name</label>
4
+ <div class="col">
5
+ <%= text_field_tag "client[name]", @client.name, class: "form-control", disabled: @client.persisted? %>
6
+ <div class="form-text">a unique identifier for this owner of persisted operations</div>
7
+ </div>
8
+ </div>
9
+ <div class="row">
10
+ <label class="col-2 col-form-label">Secret</label>
11
+ <div class="col">
12
+ <%= textarea_tag "client[secret]", @client.secret, class: "form-control" %>
13
+ <div class="form-text">authentication credential for <code>sync</code> transactions</div>
14
+ </div>
15
+ </div>
16
+ <div class="row">
17
+ <div class="col-auto">
18
+ <%= submit_tag "Save", class: "btn btn-outline-primary" %>
19
+ </div>
20
+ <div class="col-auto">
21
+ <%= link_to "Back", graphql_dashboard.operation_store_clients_path, class: "btn btn-outline-secondary" %>
22
+ </div>
23
+ </div>
24
+ <% end %>
@@ -0,0 +1,21 @@
1
+ <% content_for(:title, "Edit #{@client.name}") %>
2
+ <div class="row">
3
+ <div class="col">
4
+ <h1>Edit <%= @client.name %></h1>
5
+ </div>
6
+ </div>
7
+ <%= render partial: "graphql/dashboard/operation_store/clients/form" %>
8
+
9
+ <hr class="mt-5">
10
+ <div class="row mt-5">
11
+ <div class="col">
12
+ <div class="alert alert-danger">
13
+ <h4>Delete <%= @client.name %></h4>
14
+ <p>If you delete this client, it will no longer be able to use stored operations.</p>
15
+ <p>There is no way to undo this action.</p>
16
+ <%= form_tag(graphql_dashboard.operation_store_client_path(name: @client.name), method: "delete") do %>
17
+ <%= submit_tag "Permanently Delete #{@client.name.inspect}", class: "btn btn-outline-danger" %>
18
+ <% end %>
19
+ </div>
20
+ </div>
21
+ </div>
@@ -0,0 +1,69 @@
1
+ <% content_for(:title, "Clients") %>
2
+ <div class="row mt-3 justify-content-between">
3
+ <div class="col-4">
4
+ <h3>
5
+ <%= pluralize(@clients_page.total_count, "Client") %>
6
+ </h3>
7
+ </div>
8
+ <div class="col-auto">
9
+ <%= link_to("New Client", graphql_dashboard.new_operation_store_client_path, class: "btn btn-outline-primary") %>
10
+ </div>
11
+ </div>
12
+
13
+ <table class="table table-striped">
14
+ <thead>
15
+ <tr>
16
+ <th><%= link_to("Name", graphql_dashboard.operation_store_clients_path, params: { order_by: "name", order_dir: ((@order_by == "name" && @order_dir != :desc) ? "desc" : "asc" )}) %></th>
17
+ <th>Operations</th>
18
+ <th>Created At</th>
19
+ <th>Last Updated</th>
20
+ <th><%= link_to("Last Used At", graphql_dashboard.operation_store_clients_path, params: { order_by: "last_used_at", order_dir: ((@order_by == "last_used_at" && @order_dir != :desc) ? "desc": "asc")}) %></th>
21
+ </tr>
22
+ </thead>
23
+ <tbody>
24
+ <% if @clients_page.total_count == 0 %>
25
+ <tr>
26
+ <td colspan="5" class="text-center">
27
+ <em>To get started, create a <%= link_to "new client", graphql_dashboard.new_operation_store_client_path %>, then <%= link_to "sync operations", "https://graphql-ruby.org/operation_store/client_workflow.html" %> to your schema.</em>
28
+ </td>
29
+ </tr>
30
+ <% else %>
31
+ <% @clients_page.items.each do |client| %>
32
+ <tr>
33
+ <td><%= link_to(client.name, graphql_dashboard.edit_operation_store_client_path(name: client.name)) %></td>
34
+ <td>
35
+ <%= link_to(graphql_dashboard.operation_store_client_operations_path(client_name: client.name)) do %>
36
+ <%= client.operations_count %><% if client.archived_operations_count > 0 %> <span class="muted">(<%= client.archived_operations_count %> archived)</span><% end %>
37
+ <% end %>
38
+ </td>
39
+ <td><%= client.created_at %></td>
40
+ <td>
41
+ <% if client.operations_count == 0 %>
42
+ &mdash;
43
+ <% else %>
44
+ <%= client.last_synced_at %>
45
+ <% end %>
46
+ </td>
47
+ <td><%= client.last_used_at || "—" %></td>
48
+ </tr>
49
+ <% end %>
50
+ <% end %>
51
+ </tbody>
52
+ </table>
53
+
54
+ <div class="row">
55
+ <div class="col-auto">
56
+ <% if @clients_page.prev_page %>
57
+ <%= link_to("« prev", graphql_dashboard.operation_store_clients_path(per_page: params[:per_page], page: @clients_page.prev_page), class: "btn btn-outline-secondary") %>
58
+ <% else %>
59
+ <button class="btn btn-outline-secondary" disabled>« prev</button>
60
+ <% end %>
61
+ </div>
62
+ <div class="col-auto">
63
+ <% if @clients_page.next_page %>
64
+ <%= link_to("next »", graphql_dashboard.operation_store_clients_path(per_page: params[:per_page], page: @clients_page.next_page), class: "btn btn-outline-secondary") %>
65
+ <% else %>
66
+ <button class="btn btn-outline-secondary" disabled>next »</button>
67
+ <% end %>
68
+ </div>
69
+ </div>
@@ -0,0 +1,7 @@
1
+ <% content_for(:title, "New Client") %>
2
+ <div class="row">
3
+ <div class="col">
4
+ <h1>New Client</h1>
5
+ </div>
6
+ </div>
7
+ <%= render partial: "graphql/dashboard/operation_store/clients/form" %>
@@ -0,0 +1,39 @@
1
+ <% content_for(:title, "Index#{@search_term ? " - #{@search_term}" : ""}") %>
2
+ <div class="row mt-2">
3
+ <h3>Schema Index</h3>
4
+ <div class="col">
5
+ <p style="margin-left: 15px;">
6
+ <%= pluralize(@index_entries_page.total_count, @search_term ? "result" : "entry") %>
7
+ </p>
8
+ </div>
9
+ <div class="col">
10
+ <form method="GET" action="<%= graphql_dashboard.operation_store_index_entries_path %>" style="margin-left: auto; margin-top:-5px;">
11
+ <div class="input-group">
12
+ <%= text_field_tag "q", @search_term, class: "form-control", placeholder: "Find types, fields, arguments, or enum values" %>
13
+ <input type="submit" value="Search" class="btn btn-outline-primary btn-sm">
14
+ </div>
15
+ </form>
16
+ </div>
17
+ </div>
18
+ <table class="table">
19
+ <thead>
20
+ <tr>
21
+ <th>Name</th>
22
+ <th># Usages</th>
23
+ <th>Last Used At</th>
24
+ </tr>
25
+ </thead>
26
+ <tbody>
27
+ <% @index_entries_page.items.each do |entry| %>
28
+ <tr>
29
+ <td><%= link_to(entry.name, graphql_dashboard.operation_store_index_entry_path(name: entry.name)) %></td>
30
+ <td><%= entry.references_count %><% if entry.archived_references_count.nil? %><span class="muted">(missing data - call `YourSchema.operation_store.reindex` to repair index)</span><% elsif entry.archived_references_count > 0 %> <span class="muted">(<%= entry.archived_references_count %> archived)</span><% end %></td>
31
+ <td><%= entry.last_used_at %></td>
32
+ </tr>
33
+ <% end %>
34
+ </tbody>
35
+ </table>
36
+
37
+ <%=
38
+ # render_partial("_pagination")
39
+ %>
@@ -0,0 +1,32 @@
1
+ <% name = @chain.pop %>
2
+ <% content_for(:title, "Index - #{@entry.name}") %>
3
+ <div class="row mt-2">
4
+ <div class="col">
5
+ <%= link_to("Index", graphql_dashboard.operation_store_index_entries_path) %>
6
+ <% @chain.each do |c| %>
7
+ > <%= link_to(c.split(".").last, graphql_dashboard.operation_store_index_entry_path(name: c)) %>
8
+ <% end %>
9
+ > <%= name.split(".").last %>
10
+ </div>
11
+ </div>
12
+ <div class="row mt-2">
13
+ <div class="col">
14
+ <h3><%= name %></h3>
15
+ <p>
16
+ Used By:
17
+ <% if @operations.any? %>
18
+ <ul>
19
+ <% @operations.each do |operation| %>
20
+ <li>
21
+ <%= link_to(operation.name, graphql_dashboard.operation_store_operation_path(digest: operation.digest)) %><% if operation.is_archived %> <span class="muted">(archived)</span><% end %>
22
+ </li>
23
+ <% end %>
24
+ </ul>
25
+ <% else %>
26
+ <i>none</i>
27
+ <% end %>
28
+ </p>
29
+
30
+ <p>Last used at: <%= @entry.last_used_at || "—" %></p>
31
+ </div>
32
+ </div>
@@ -0,0 +1,81 @@
1
+ <div class="row mt-2">
2
+ <% if @client_operations %>
3
+ <%= content_for(:title, "#{params[:client_name]} Operations") %>
4
+ <div class="col">
5
+ <h3><%= params[:client_name] %></h3>
6
+ <ul class="nav nav-tabs">
7
+ <li class="nav-item">
8
+ <%= link_to "#{@unarchived_operations_count} Active", graphql_dashboard.operation_store_client_operations_path(client_name: params[:client_name]), class: "nav-link #{@is_archived ? "" : "active"}" %>
9
+ </li>
10
+ <li class="nav-item">
11
+ <%= link_to "#{@archived_operations_count} Archived", graphql_dashboard.archived_operation_store_client_operations_path(client_name: params[:client_name]), class: "nav-link #{@is_archived ? "active" : ""}" %>
12
+ </li>
13
+ </ul>
14
+ </div>
15
+ <% else %>
16
+ <%= content_for(:title, "Operations") %>
17
+ <div class="col">
18
+ <ul class="nav nav-tabs">
19
+ <li class="nav-item">
20
+ <%= link_to "#{@unarchived_operations_count} Active", graphql_dashboard.operation_store_operations_path, class: "nav-link #{@is_archived ? "" : "active"}" %>
21
+ </li>
22
+ <li class="nav-item">
23
+ <%= link_to "#{@archived_operations_count} Archived", graphql_dashboard.archived_operation_store_operations_path, class: "nav-link #{@is_archived ? "active" : ""}" %>
24
+ </li>
25
+ </ul>
26
+ </div>
27
+ <% end %>
28
+ </div>
29
+
30
+ <div class="row">
31
+ <div class="col">
32
+ <table class="table table-striped">
33
+ <thead>
34
+ <tr>
35
+ <th><%= link_to "Name", graphql_dashboard.operation_store_operations_path({ order_by: "name", order_dir: params[:order_dir] == "asc" ? "desc" : "asc" }) %></th>
36
+ <% if @client_operations %>
37
+ <th>Alias</th>
38
+ <% else %>
39
+ <th># Clients</th>
40
+ <% end %>
41
+ <th>Digest</th>
42
+ <th><%= link_to "Last Used At", graphql_dashboard.operation_store_operations_path({ order_by: "last_used_at", order_dir: params[:order_dir] == "asc" ? "desc" : "asc" }) %></th>
43
+ <th>
44
+ <button class="btn btn-sm btn-outline-primary" data-archive-client="<%= params[:client_name] %>" data-archive-all="<%= params[:client_name] ? nil : "true" %>">
45
+ <%= @is_archived ? "Unarchive" : "Archive" %>
46
+ </button>
47
+ </th>
48
+ </tr>
49
+ </thead>
50
+ <tbody>
51
+ <% if @operations_page.total_count == 0 %>
52
+ <tr>
53
+ <td colspan="5" class="text-center">
54
+ <% if @is_archived %>
55
+ <em><%= link_to "Archived operations", "https://graphql-ruby.org/operation_store/server_management.html#archiving-and-deleting-data" %> will appear here.</em>
56
+ <% else %>
57
+ <em>Add your first stored operations with <%= link_to "sync", "https://graphql-ruby.org/operation_store/client_workflow.html" %>.</em>
58
+ <% end %>
59
+ </td>
60
+ </tr>
61
+ <% else %>
62
+ <% @operations_page.items.each do |operation| %>
63
+ <tr>
64
+ <td><%= link_to(operation.name, graphql_dashboard.operation_store_operation_path(digest: operation.digest)) %></td>
65
+ <% if @client_operations %>
66
+ <td><code><%= operation.operation_alias %></code></td>
67
+ <% else %>
68
+ <td><%= operation.clients_count %></td>
69
+ <% end %>
70
+ <td><code><%= operation.digest %></code></td>
71
+ <td><%= operation.last_used_at %></td>
72
+ <td>
73
+ <%= check_box_tag("value", (@client_operations ? operation.operation_alias : operation.digest), class: "archive-check form-check-input") %>
74
+ </td>
75
+ </tr>
76
+ <% end %>
77
+ <% end %>
78
+ </tbody>
79
+ </table>
80
+ </div>
81
+ </div>
@@ -0,0 +1,71 @@
1
+ <% content_for(:title, "View #{params[:digest]}") %>
2
+ <% if @operation.nil? %>
3
+ <div class="row">
4
+ <div class="col">
5
+ <p>No stored operation found for <code><%= params[:digest] %></code></p>
6
+ </div>
7
+ </div>
8
+ <% else %>
9
+ <div class="row">
10
+ <div class="col">
11
+ <h2>
12
+ <%= @operation.name %>
13
+ <% if @operation.is_archived %><small> (archived)</small><% end %>
14
+ </h2>
15
+ </div>
16
+ </div>
17
+ <div class="row mt-3">
18
+ <div class="col">
19
+ <p>Aliases</p>
20
+ <% if @client_operations.empty? %>
21
+ <p><em>None</em></p>
22
+ <% else %>
23
+ <ul>
24
+ <% @client_operations.each do |cl_op| %>
25
+ <li>
26
+ <code><%= cl_op.operation_alias %></code>
27
+ <%= link_to(cl_op.client_name, graphql_dashboard.operation_store_client_operations_path(client_name: cl_op.client_name)) %>
28
+ <%= cl_op.is_archived ? " (archived)" : "" %>
29
+ </li>
30
+ <% end %>
31
+ </ul>
32
+ <% end %>
33
+ </div>
34
+ </div>
35
+ <div class="row">
36
+ <div class="col">
37
+ <p>Last Used At</p>
38
+ <p><code><%= @operation.last_used_at %></code></p>
39
+ </div>
40
+ </div>
41
+ <div class="row">
42
+ <div class="col">
43
+ <p>Source</p>
44
+ <%= textarea_tag "_source", @graphql_source, class: "graphql-highlight form-control", disabled: true, rows: @graphql_source.count("\n") + 1 %>
45
+ </div>
46
+ </div>
47
+ <div class="row mt-3">
48
+ <div class="col">
49
+ <p>References</p>
50
+ <ul>
51
+ <% @entries.each do |entry| %>
52
+ <li>
53
+ <%= link_to(entry.name, graphql_dashboard.operation_store_index_entry_path(name: entry.name)) %>
54
+ </li>
55
+ <% end %>
56
+ </ul>
57
+ </div>
58
+ </div>
59
+ <div class="row mt-3">
60
+ <div class="col">
61
+ <p>Digest</p>
62
+ <p><code><%= @operation.digest %></code></p>
63
+ </div>
64
+ </div>
65
+ <div class="row mt-3">
66
+ <div class="col">
67
+ <p>Minified Source</p>
68
+ <%= textarea_tag "_source", @operation.body, class: "graphql-highlight form-control", disabled: true, rows: @operation.body.count("\n") + 1 %>
69
+ </div>
70
+ </div>
71
+ <% end %>
@@ -0,0 +1,41 @@
1
+ <% content_for(:title, "Subscription #{params[:id]}") %>
2
+ <div class="row mt-3">
3
+ <div class="col">
4
+ <h3>Subscription: <code><%= params[:id] %></code></h3>
5
+ </div>
6
+ </div>
7
+
8
+ <% if @query_data.nil? %>
9
+ <div class="row">
10
+ <div class="col">
11
+ <p class="muted"><i>This subscription was not found or is no longer active.</i></p>
12
+ </div>
13
+ </div>
14
+ <% else %>
15
+ <div class="row">
16
+ <div class="col">
17
+ <p>Created at <%= @query_data[:created_at] %>, last triggered at <%= @query_data[:last_triggered_at] || "--" %></p>
18
+
19
+ <p>Subscribed? <code><%= @still_subscribed ? "YES" : "NO" %></code></p>
20
+ <p>Broadcast? <code><%= @is_broadcast ? "YES" : "NO" %></code> <% if @is_broadcast %>
21
+ <small class="muted"><% if @subscribers_count.nil? %>
22
+ This subscription may have multiple subscribers.
23
+ <% else %>
24
+ (<%= pluralize(@subscribers_count, "subscriber") %>)
25
+ <% end %></small>
26
+ <% end %></p>
27
+
28
+ <p>Context:</p>
29
+ <pre><%= @query_data[:context].inspect %></pre>
30
+
31
+ <p>Variables:</p>
32
+ <pre><%= @query_data[:variables].inspect %></pre>
33
+
34
+ <p>Operation Name:</p>
35
+ <pre><%= @query_data[:operation_name].inspect %></pre>
36
+
37
+ <p>Query String:</p>
38
+ <%= textarea_tag "_source", @query_data[:query_string], class: "graphql-highlight form-control", disabled: true, rows: @query_data[:query_string].count("\n") + 1 %>
39
+ </div>
40
+ </div>
41
+ <% end %>