ecoportal-api-graphql 2.0.0 → 3.0.0

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 (393) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +793 -14
  3. data/LICENSE +21 -21
  4. data/README.gem.md +53 -0
  5. data/lib/ecoportal/api/common/graphql/auth_service.rb +115 -115
  6. data/lib/ecoportal/api/common/graphql/class_helpers.rb +46 -46
  7. data/lib/ecoportal/api/common/graphql/client.rb +107 -69
  8. data/lib/ecoportal/api/common/graphql/hash_helpers.rb +105 -105
  9. data/lib/ecoportal/api/common/graphql/http_client.rb +124 -8
  10. data/lib/ecoportal/api/common/graphql/model/as_input.rb +54 -54
  11. data/lib/ecoportal/api/common/graphql/model/diffable/classic_diff_service.rb +49 -49
  12. data/lib/ecoportal/api/common/graphql/model/diffable/diff_service.rb +188 -188
  13. data/lib/ecoportal/api/common/graphql/model/diffable/hash_diff.rb +55 -55
  14. data/lib/ecoportal/api/common/graphql/model/diffable/hash_diff_nesting.rb +295 -295
  15. data/lib/ecoportal/api/common/graphql/model/diffable/leaf_diff_service.rb +1 -1
  16. data/lib/ecoportal/api/common/graphql/model.rb +17 -17
  17. data/lib/ecoportal/api/common/graphql/patches.rb +1 -1
  18. data/lib/ecoportal/api/common/graphql/query_integration.rb +45 -45
  19. data/lib/ecoportal/api/common/graphql.rb +16 -16
  20. data/lib/ecoportal/api/common.graphql.rb +8 -8
  21. data/lib/ecoportal/api/graphql/base/action_category.rb +15 -15
  22. data/lib/ecoportal/api/graphql/base/ai_summary_version.rb +1 -1
  23. data/lib/ecoportal/api/graphql/base/contractor_entity.rb +24 -24
  24. data/lib/ecoportal/api/graphql/base/date_time.rb +12 -12
  25. data/lib/ecoportal/api/graphql/base/delta_result.rb +16 -16
  26. data/lib/ecoportal/api/graphql/base/field.rb +12 -12
  27. data/lib/ecoportal/api/graphql/base/file_attachment.rb +15 -15
  28. data/lib/ecoportal/api/graphql/base/location_node.rb +14 -14
  29. data/lib/ecoportal/api/graphql/base/location_structure/draft/structure.rb +37 -37
  30. data/lib/ecoportal/api/graphql/base/location_structure/draft.rb +93 -93
  31. data/lib/ecoportal/api/graphql/base/page/data_field/actions_list.rb +9 -9
  32. data/lib/ecoportal/api/graphql/base/page/data_field/ai_summary.rb +18 -18
  33. data/lib/ecoportal/api/graphql/base/page/data_field/checklist.rb +29 -29
  34. data/lib/ecoportal/api/graphql/base/page/data_field/collection.rb +1 -1
  35. data/lib/ecoportal/api/graphql/base/page/data_field/cross_reference.rb +1 -1
  36. data/lib/ecoportal/api/graphql/base/page/data_field/date_field.rb +23 -23
  37. data/lib/ecoportal/api/graphql/base/page/data_field/geo.rb +24 -24
  38. data/lib/ecoportal/api/graphql/base/page/data_field/image_gallery.rb +160 -12
  39. data/lib/ecoportal/api/graphql/base/page/data_field/law.rb +8 -8
  40. data/lib/ecoportal/api/graphql/base/page/data_field/mailbox.rb +9 -9
  41. data/lib/ecoportal/api/graphql/base/page/data_field/plain_text.rb +17 -17
  42. data/lib/ecoportal/api/graphql/base/page/data_field/rich_text.rb +26 -26
  43. data/lib/ecoportal/api/graphql/base/page/data_field/signature.rb +9 -9
  44. data/lib/ecoportal/api/graphql/base/page/data_field/smart_fill.rb +17 -17
  45. data/lib/ecoportal/api/graphql/base/page/data_field/table.rb +9 -9
  46. data/lib/ecoportal/api/graphql/base/page/data_field/tag_field.rb +21 -21
  47. data/lib/ecoportal/api/graphql/base/page/phased/stage.rb +51 -0
  48. data/lib/ecoportal/api/graphql/base/page/phased.rb +15 -15
  49. data/lib/ecoportal/api/graphql/base/page/section.rb +48 -48
  50. data/lib/ecoportal/api/graphql/base/page_info.rb +12 -12
  51. data/lib/ecoportal/api/graphql/base/pages_workflow/operation_interface.rb +39 -39
  52. data/lib/ecoportal/api/graphql/base/pages_workflow/operations/assign_to.rb +27 -27
  53. data/lib/ecoportal/api/graphql/base/pages_workflow/operations/send_notification.rb +30 -30
  54. data/lib/ecoportal/api/graphql/base/pages_workflow/recipient_config.rb +34 -34
  55. data/lib/ecoportal/api/graphql/base/pages_workflow.rb +35 -35
  56. data/lib/ecoportal/api/graphql/base/person_member.rb +22 -22
  57. data/lib/ecoportal/api/graphql/base/preview_page.rb +23 -23
  58. data/lib/ecoportal/api/graphql/base/register.rb +1 -1
  59. data/lib/ecoportal/api/graphql/base/resource.rb +13 -13
  60. data/lib/ecoportal/api/graphql/base/temp_image.rb +28 -0
  61. data/lib/ecoportal/api/graphql/base/template/change_log_entry.rb +118 -0
  62. data/lib/ecoportal/api/graphql/base/template.rb +2 -0
  63. data/lib/ecoportal/api/graphql/base.rb +1 -0
  64. data/lib/ecoportal/api/graphql/builder/action.rb +41 -41
  65. data/lib/ecoportal/api/graphql/builder/location_structure/draft.rb +64 -64
  66. data/lib/ecoportal/api/graphql/builder/location_structure.rb +40 -40
  67. data/lib/ecoportal/api/graphql/builder/register/preset_view.rb +84 -84
  68. data/lib/ecoportal/api/graphql/builder/register.rb +49 -49
  69. data/lib/ecoportal/api/graphql/builder/template.rb +37 -4
  70. data/lib/ecoportal/api/graphql/builder/template_builder.rb +21 -2
  71. data/lib/ecoportal/api/graphql/compat/filter_translator.rb +1 -1
  72. data/lib/ecoportal/api/graphql/compat/page_reference.rb +23 -23
  73. data/lib/ecoportal/api/graphql/compat/registers.rb +84 -84
  74. data/lib/ecoportal/api/graphql/compat/search_results.rb +33 -33
  75. data/lib/ecoportal/api/graphql/compat.rb +17 -17
  76. data/lib/ecoportal/api/graphql/concerns/data_field_access.rb +71 -71
  77. data/lib/ecoportal/api/graphql/concerns/fragment_definitions.rb +68 -68
  78. data/lib/ecoportal/api/graphql/concerns/snake_camel_access.rb +60 -60
  79. data/lib/ecoportal/api/graphql/connection/preset_view.rb +11 -11
  80. data/lib/ecoportal/api/graphql/connection/template_change_log.rb +19 -0
  81. data/lib/ecoportal/api/graphql/connection.rb +1 -0
  82. data/lib/ecoportal/api/graphql/diff/change.rb +7 -2
  83. data/lib/ecoportal/api/graphql/diff/command_synthesizer.rb +19 -1
  84. data/lib/ecoportal/api/graphql/diff/version_diff.rb +13 -6
  85. data/lib/ecoportal/api/graphql/error/locations_error/fetch_nested.rb +51 -51
  86. data/lib/ecoportal/api/graphql/error/locations_error.rb +28 -28
  87. data/lib/ecoportal/api/graphql/error/locations_validation_error.rb +20 -20
  88. data/lib/ecoportal/api/graphql/error/validation_errors.rb +28 -28
  89. data/lib/ecoportal/api/graphql/error.rb +12 -12
  90. data/lib/ecoportal/api/graphql/file_upload/client.rb +140 -35
  91. data/lib/ecoportal/api/graphql/file_upload.rb +10 -10
  92. data/lib/ecoportal/api/graphql/fragment/action.rb +65 -65
  93. data/lib/ecoportal/api/graphql/fragment/action_category.rb +17 -17
  94. data/lib/ecoportal/api/graphql/fragment/contractor_entity.rb +20 -20
  95. data/lib/ecoportal/api/graphql/fragment/locations_error.rb +19 -19
  96. data/lib/ecoportal/api/graphql/fragment/page.rb +1 -0
  97. data/lib/ecoportal/api/graphql/fragment/pages/common_page_union.rb +10 -3
  98. data/lib/ecoportal/api/graphql/fragment/pages.rb +15 -15
  99. data/lib/ecoportal/api/graphql/fragment/pagination.rb +17 -17
  100. data/lib/ecoportal/api/graphql/fragment/permissions.rb +0 -2
  101. data/lib/ecoportal/api/graphql/fragment/template_change_log.rb +102 -0
  102. data/lib/ecoportal/api/graphql/fragment.rb +1 -0
  103. data/lib/ecoportal/api/graphql/helpers/locations_tree.rb +41 -41
  104. data/lib/ecoportal/api/graphql/helpers.rb +10 -10
  105. data/lib/ecoportal/api/graphql/input/action/archive.rb +14 -14
  106. data/lib/ecoportal/api/graphql/input/action/create.rb +13 -13
  107. data/lib/ecoportal/api/graphql/input/action.rb +14 -14
  108. data/lib/ecoportal/api/graphql/input/contractor_entity/create.rb +14 -14
  109. data/lib/ecoportal/api/graphql/input/contractor_entity/destroy.rb +13 -13
  110. data/lib/ecoportal/api/graphql/input/delta_input.rb +16 -16
  111. data/lib/ecoportal/api/graphql/input/id_diff.rb +11 -11
  112. data/lib/ecoportal/api/graphql/input/location_structure/archive_command.rb +13 -13
  113. data/lib/ecoportal/api/graphql/input/location_structure/delete_command.rb +13 -13
  114. data/lib/ecoportal/api/graphql/input/location_structure/draft/create.rb +15 -15
  115. data/lib/ecoportal/api/graphql/input/location_structure/draft/delete.rb +15 -15
  116. data/lib/ecoportal/api/graphql/input/location_structure/draft/drop_bad_commands.rb +16 -16
  117. data/lib/ecoportal/api/graphql/input/location_structure/draft/publish.rb +16 -16
  118. data/lib/ecoportal/api/graphql/input/location_structure/draft.rb +19 -19
  119. data/lib/ecoportal/api/graphql/input/location_structure/insert_command.rb +21 -13
  120. data/lib/ecoportal/api/graphql/input/location_structure/move_command.rb +14 -14
  121. data/lib/ecoportal/api/graphql/input/location_structure/reorder_command.rb +13 -13
  122. data/lib/ecoportal/api/graphql/input/location_structure/unarchive_command.rb +13 -13
  123. data/lib/ecoportal/api/graphql/input/location_structure.rb +20 -20
  124. data/lib/ecoportal/api/graphql/input/page/archive.rb +14 -14
  125. data/lib/ecoportal/api/graphql/input/page/build_from_template.rb +13 -13
  126. data/lib/ecoportal/api/graphql/input/page/create_draft.rb +13 -13
  127. data/lib/ecoportal/api/graphql/input/page/create_from_template.rb +18 -18
  128. data/lib/ecoportal/api/graphql/input/page/delete_draft.rb +13 -13
  129. data/lib/ecoportal/api/graphql/input/page/publish_draft.rb +13 -13
  130. data/lib/ecoportal/api/graphql/input/page/review_task.rb +27 -14
  131. data/lib/ecoportal/api/graphql/input/page/unarchive.rb +14 -14
  132. data/lib/ecoportal/api/graphql/input/page/update.rb +109 -6
  133. data/lib/ecoportal/api/graphql/input/page.rb +26 -26
  134. data/lib/ecoportal/api/graphql/input/preset_view/create.rb +18 -18
  135. data/lib/ecoportal/api/graphql/input/preset_view/permission.rb +16 -16
  136. data/lib/ecoportal/api/graphql/input/preset_view/update.rb +1 -1
  137. data/lib/ecoportal/api/graphql/input/preset_view.rb +14 -14
  138. data/lib/ecoportal/api/graphql/input/register/create.rb +18 -18
  139. data/lib/ecoportal/api/graphql/input/register/update.rb +15 -15
  140. data/lib/ecoportal/api/graphql/input/register.rb +13 -13
  141. data/lib/ecoportal/api/graphql/input/search.rb +13 -13
  142. data/lib/ecoportal/api/graphql/input/search_conf/ai_generator.rb +234 -234
  143. data/lib/ecoportal/api/graphql/input/search_conf.rb +1 -1
  144. data/lib/ecoportal/api/graphql/input/search_filter.rb +12 -12
  145. data/lib/ecoportal/api/graphql/input/search_sorter.rb +11 -11
  146. data/lib/ecoportal/api/graphql/input/workflow_command/add_action_tag.rb +18 -18
  147. data/lib/ecoportal/api/graphql/input/workflow_command/add_binding.rb +18 -18
  148. data/lib/ecoportal/api/graphql/input/workflow_command/add_comment_tagging_user_group.rb +18 -18
  149. data/lib/ecoportal/api/graphql/input/workflow_command/add_default_direct_strategy_user.rb +18 -18
  150. data/lib/ecoportal/api/graphql/input/workflow_command/add_default_strategy.rb +18 -18
  151. data/lib/ecoportal/api/graphql/input/workflow_command/add_direct_strategy_user.rb +18 -18
  152. data/lib/ecoportal/api/graphql/input/workflow_command/add_field.rb +10 -9
  153. data/lib/ecoportal/api/graphql/input/workflow_command/add_force.rb +18 -18
  154. data/lib/ecoportal/api/graphql/input/workflow_command/add_linked_field_config.rb +23 -23
  155. data/lib/ecoportal/api/graphql/input/workflow_command/add_linked_helper.rb +18 -18
  156. data/lib/ecoportal/api/graphql/input/workflow_command/add_operation.rb +18 -18
  157. data/lib/ecoportal/api/graphql/input/workflow_command/add_operation_direct_strategy_user.rb +18 -18
  158. data/lib/ecoportal/api/graphql/input/workflow_command/add_operation_strategy.rb +18 -18
  159. data/lib/ecoportal/api/graphql/input/workflow_command/add_recipient_action_type.rb +18 -18
  160. data/lib/ecoportal/api/graphql/input/workflow_command/add_recipient_filter.rb +18 -18
  161. data/lib/ecoportal/api/graphql/input/workflow_command/add_recipient_people_field.rb +18 -18
  162. data/lib/ecoportal/api/graphql/input/workflow_command/add_recipient_task_config.rb +18 -18
  163. data/lib/ecoportal/api/graphql/input/workflow_command/add_recipient_user.rb +18 -18
  164. data/lib/ecoportal/api/graphql/input/workflow_command/add_scheduled_callback.rb +23 -23
  165. data/lib/ecoportal/api/graphql/input/workflow_command/add_scheduled_callback_action.rb +18 -18
  166. data/lib/ecoportal/api/graphql/input/workflow_command/add_section.rb +18 -18
  167. data/lib/ecoportal/api/graphql/input/workflow_command/add_select_field_option.rb +25 -19
  168. data/lib/ecoportal/api/graphql/input/workflow_command/add_stage_section.rb +18 -18
  169. data/lib/ecoportal/api/graphql/input/workflow_command/add_stage_tag.rb +18 -18
  170. data/lib/ecoportal/api/graphql/input/workflow_command/add_strategy.rb +18 -18
  171. data/lib/ecoportal/api/graphql/input/workflow_command/add_task.rb +18 -18
  172. data/lib/ecoportal/api/graphql/input/workflow_command/add_task_assignment_user_group.rb +18 -18
  173. data/lib/ecoportal/api/graphql/input/workflow_command/add_workflow_callback.rb +18 -18
  174. data/lib/ecoportal/api/graphql/input/workflow_command/collapse_section.rb +18 -18
  175. data/lib/ecoportal/api/graphql/input/workflow_command/edit_binding.rb +18 -18
  176. data/lib/ecoportal/api/graphql/input/workflow_command/edit_creator_permissions.rb +18 -18
  177. data/lib/ecoportal/api/graphql/input/workflow_command/edit_default_strategy.rb +18 -18
  178. data/lib/ecoportal/api/graphql/input/workflow_command/edit_field_configuration.rb +7 -2
  179. data/lib/ecoportal/api/graphql/input/workflow_command/edit_force.rb +21 -18
  180. data/lib/ecoportal/api/graphql/input/workflow_command/edit_gauge_field_stop.rb +19 -19
  181. data/lib/ecoportal/api/graphql/input/workflow_command/edit_linked_field_config.rb +19 -19
  182. data/lib/ecoportal/api/graphql/input/workflow_command/edit_linked_helper.rb +18 -18
  183. data/lib/ecoportal/api/graphql/input/workflow_command/edit_operation.rb +18 -18
  184. data/lib/ecoportal/api/graphql/input/workflow_command/edit_operation_strategy.rb +18 -18
  185. data/lib/ecoportal/api/graphql/input/workflow_command/edit_reminder.rb +18 -18
  186. data/lib/ecoportal/api/graphql/input/workflow_command/edit_required_sign_offs.rb +18 -18
  187. data/lib/ecoportal/api/graphql/input/workflow_command/edit_restrict_comment_tagging.rb +18 -18
  188. data/lib/ecoportal/api/graphql/input/workflow_command/edit_restrict_task_assignment.rb +18 -18
  189. data/lib/ecoportal/api/graphql/input/workflow_command/edit_scheduled_callback.rb +22 -22
  190. data/lib/ecoportal/api/graphql/input/workflow_command/edit_section_header.rb +18 -18
  191. data/lib/ecoportal/api/graphql/input/workflow_command/edit_select_field_option.rb +23 -19
  192. data/lib/ecoportal/api/graphql/input/workflow_command/edit_stage.rb +18 -18
  193. data/lib/ecoportal/api/graphql/input/workflow_command/edit_strategy.rb +18 -18
  194. data/lib/ecoportal/api/graphql/input/workflow_command/edit_task_due.rb +18 -18
  195. data/lib/ecoportal/api/graphql/input/workflow_command/edit_template_basic_settings.rb +7 -2
  196. data/lib/ecoportal/api/graphql/input/workflow_command/edit_template_container_uid.rb +1 -1
  197. data/lib/ecoportal/api/graphql/input/workflow_command/edit_trigger.rb +18 -18
  198. data/lib/ecoportal/api/graphql/input/workflow_command/expand_section.rb +18 -18
  199. data/lib/ecoportal/api/graphql/input/workflow_command/field_config/contractor_entities.rb +28 -24
  200. data/lib/ecoportal/api/graphql/input/workflow_command/field_config/cross_reference.rb +8 -2
  201. data/lib/ecoportal/api/graphql/input/workflow_command/field_config/gauge.rb +20 -20
  202. data/lib/ecoportal/api/graphql/input/workflow_command/field_config/location_field.rb +24 -24
  203. data/lib/ecoportal/api/graphql/input/workflow_command/field_config/plain_text.rb +8 -2
  204. data/lib/ecoportal/api/graphql/input/workflow_command/field_config/signature.rb +20 -20
  205. data/lib/ecoportal/api/graphql/input/workflow_command/field_config/table.rb +25 -25
  206. data/lib/ecoportal/api/graphql/input/workflow_command/manage_copy_page_configuration.rb +47 -0
  207. data/lib/ecoportal/api/graphql/input/workflow_command/move_section_to_stage.rb +33 -0
  208. data/lib/ecoportal/api/graphql/input/workflow_command/move_stage.rb +18 -18
  209. data/lib/ecoportal/api/graphql/input/workflow_command/remove_action_tag.rb +18 -18
  210. data/lib/ecoportal/api/graphql/input/workflow_command/remove_binding.rb +18 -18
  211. data/lib/ecoportal/api/graphql/input/workflow_command/remove_callback.rb +18 -18
  212. data/lib/ecoportal/api/graphql/input/workflow_command/remove_comment_tagging_user_group.rb +18 -18
  213. data/lib/ecoportal/api/graphql/input/workflow_command/remove_default_direct_strategy_user.rb +18 -18
  214. data/lib/ecoportal/api/graphql/input/workflow_command/remove_default_strategy.rb +18 -18
  215. data/lib/ecoportal/api/graphql/input/workflow_command/remove_direct_strategy_user.rb +18 -18
  216. data/lib/ecoportal/api/graphql/input/workflow_command/remove_field.rb +18 -18
  217. data/lib/ecoportal/api/graphql/input/workflow_command/remove_force.rb +18 -18
  218. data/lib/ecoportal/api/graphql/input/workflow_command/remove_linked_helper.rb +18 -18
  219. data/lib/ecoportal/api/graphql/input/workflow_command/remove_operation.rb +18 -18
  220. data/lib/ecoportal/api/graphql/input/workflow_command/remove_operation_direct_strategy_user.rb +18 -18
  221. data/lib/ecoportal/api/graphql/input/workflow_command/remove_operation_strategy.rb +18 -18
  222. data/lib/ecoportal/api/graphql/input/workflow_command/remove_recipient_action_type.rb +18 -18
  223. data/lib/ecoportal/api/graphql/input/workflow_command/remove_recipient_filter.rb +18 -18
  224. data/lib/ecoportal/api/graphql/input/workflow_command/remove_recipient_people_field.rb +18 -18
  225. data/lib/ecoportal/api/graphql/input/workflow_command/remove_recipient_task_config.rb +18 -18
  226. data/lib/ecoportal/api/graphql/input/workflow_command/remove_recipient_user.rb +18 -18
  227. data/lib/ecoportal/api/graphql/input/workflow_command/remove_scheduled_callback.rb +18 -18
  228. data/lib/ecoportal/api/graphql/input/workflow_command/remove_section.rb +18 -18
  229. data/lib/ecoportal/api/graphql/input/workflow_command/remove_stage.rb +18 -18
  230. data/lib/ecoportal/api/graphql/input/workflow_command/remove_stage_section.rb +18 -18
  231. data/lib/ecoportal/api/graphql/input/workflow_command/remove_stage_tag.rb +18 -18
  232. data/lib/ecoportal/api/graphql/input/workflow_command/remove_strategy.rb +18 -18
  233. data/lib/ecoportal/api/graphql/input/workflow_command/remove_task.rb +18 -18
  234. data/lib/ecoportal/api/graphql/input/workflow_command/remove_task_assignment_user_group.rb +18 -18
  235. data/lib/ecoportal/api/graphql/input/workflow_command/remove_task_due.rb +18 -18
  236. data/lib/ecoportal/api/graphql/input/workflow_command/remove_task_priority_level.rb +18 -18
  237. data/lib/ecoportal/api/graphql/input/workflow_command.rb +5 -0
  238. data/lib/ecoportal/api/graphql/interface/base_page.rb +14 -0
  239. data/lib/ecoportal/api/graphql/interface/location_structure/node.rb +43 -43
  240. data/lib/ecoportal/api/graphql/interface/location_structure.rb +14 -14
  241. data/lib/ecoportal/api/graphql/interface.rb +11 -11
  242. data/lib/ecoportal/api/graphql/logic/base_model.rb +15 -15
  243. data/lib/ecoportal/api/graphql/logic/base_query.rb +260 -193
  244. data/lib/ecoportal/api/graphql/logic/mutation.rb +59 -59
  245. data/lib/ecoportal/api/graphql/logic/payload.rb +42 -42
  246. data/lib/ecoportal/api/graphql/logic/query.rb +23 -23
  247. data/lib/ecoportal/api/graphql/logic/query_array.rb +30 -30
  248. data/lib/ecoportal/api/graphql/logic/query_connection.rb +48 -48
  249. data/lib/ecoportal/api/graphql/logic.rb +18 -18
  250. data/lib/ecoportal/api/graphql/model/account.rb +15 -15
  251. data/lib/ecoportal/api/graphql/model/action.rb +22 -22
  252. data/lib/ecoportal/api/graphql/model/ai_summary_version.rb +10 -10
  253. data/lib/ecoportal/api/graphql/model/contractor_entity.rb +12 -12
  254. data/lib/ecoportal/api/graphql/model/field.rb +10 -10
  255. data/lib/ecoportal/api/graphql/model/file_attachment.rb +10 -10
  256. data/lib/ecoportal/api/graphql/model/file_container.rb +11 -11
  257. data/lib/ecoportal/api/graphql/model/location_node.rb +14 -14
  258. data/lib/ecoportal/api/graphql/model/location_structure/draft/structure.rb +15 -15
  259. data/lib/ecoportal/api/graphql/model/location_structure/draft.rb +15 -15
  260. data/lib/ecoportal/api/graphql/model/location_structure.rb +16 -16
  261. data/lib/ecoportal/api/graphql/model/organization.rb +9 -0
  262. data/lib/ecoportal/api/graphql/model/page/basic.rb +14 -14
  263. data/lib/ecoportal/api/graphql/model/page/data_field.rb +12 -12
  264. data/lib/ecoportal/api/graphql/model/page/phased/stage.rb +14 -14
  265. data/lib/ecoportal/api/graphql/model/page/phased.rb +17 -0
  266. data/lib/ecoportal/api/graphql/model/page/section.rb +12 -12
  267. data/lib/ecoportal/api/graphql/model/page_union.rb +21 -21
  268. data/lib/ecoportal/api/graphql/model/pages_workflow.rb +20 -20
  269. data/lib/ecoportal/api/graphql/model/permissions.rb +6 -0
  270. data/lib/ecoportal/api/graphql/model/preset_view.rb +10 -10
  271. data/lib/ecoportal/api/graphql/model/preview_page.rb +10 -10
  272. data/lib/ecoportal/api/graphql/model/register.rb +10 -10
  273. data/lib/ecoportal/api/graphql/model/resource.rb +13 -13
  274. data/lib/ecoportal/api/graphql/model/temp_image.rb +10 -0
  275. data/lib/ecoportal/api/graphql/model/template/binding.rb +60 -0
  276. data/lib/ecoportal/api/graphql/model/template/change_log_entry.rb +19 -0
  277. data/lib/ecoportal/api/graphql/model/template/command_grouper.rb +107 -0
  278. data/lib/ecoportal/api/graphql/model/template/command_normalizer.rb +116 -0
  279. data/lib/ecoportal/api/graphql/model/template/command_synthesis.rb +262 -0
  280. data/lib/ecoportal/api/graphql/model/template/field.rb +68 -0
  281. data/lib/ecoportal/api/graphql/model/template/force.rb +65 -0
  282. data/lib/ecoportal/api/graphql/model/template/helper.rb +32 -0
  283. data/lib/ecoportal/api/graphql/model/template/instance.rb +202 -0
  284. data/lib/ecoportal/api/graphql/model/template/node.rb +78 -0
  285. data/lib/ecoportal/api/graphql/model/template/option.rb +49 -0
  286. data/lib/ecoportal/api/graphql/model/template/read.rb +164 -0
  287. data/lib/ecoportal/api/graphql/model/template/section.rb +82 -0
  288. data/lib/ecoportal/api/graphql/model/template/stage.rb +49 -0
  289. data/lib/ecoportal/api/graphql/model/template/staged_executor.rb +236 -0
  290. data/lib/ecoportal/api/graphql/model/template.rb +37 -1
  291. data/lib/ecoportal/api/graphql/model/user.rb +14 -14
  292. data/lib/ecoportal/api/graphql/model.rb +1 -0
  293. data/lib/ecoportal/api/graphql/mutation/action/archive.rb +41 -41
  294. data/lib/ecoportal/api/graphql/mutation/action/create.rb +40 -40
  295. data/lib/ecoportal/api/graphql/mutation/action/update.rb +40 -40
  296. data/lib/ecoportal/api/graphql/mutation/action.rb +14 -14
  297. data/lib/ecoportal/api/graphql/mutation/ai_summary/generate.rb +1 -1
  298. data/lib/ecoportal/api/graphql/mutation/ai_summary/submit_feedback.rb +1 -1
  299. data/lib/ecoportal/api/graphql/mutation/ai_summary.rb +13 -13
  300. data/lib/ecoportal/api/graphql/mutation/contractor_entity/create.rb +40 -40
  301. data/lib/ecoportal/api/graphql/mutation/contractor_entity/destroy.rb +40 -40
  302. data/lib/ecoportal/api/graphql/mutation/contractor_entity/update.rb +40 -40
  303. data/lib/ecoportal/api/graphql/mutation/file_container/upload.rb +11 -4
  304. data/lib/ecoportal/api/graphql/mutation/image/upload.rb +88 -0
  305. data/lib/ecoportal/api/graphql/mutation/image.rb +14 -0
  306. data/lib/ecoportal/api/graphql/mutation/location_structure/apply_commands.rb +54 -54
  307. data/lib/ecoportal/api/graphql/mutation/location_structure/draft/add_commands.rb +55 -55
  308. data/lib/ecoportal/api/graphql/mutation/location_structure/draft/create.rb +54 -54
  309. data/lib/ecoportal/api/graphql/mutation/location_structure/draft/delete.rb +43 -43
  310. data/lib/ecoportal/api/graphql/mutation/location_structure/draft/drop_bad_commands.rb +56 -56
  311. data/lib/ecoportal/api/graphql/mutation/location_structure/draft/publish.rb +66 -66
  312. data/lib/ecoportal/api/graphql/mutation/location_structure/draft.rb +18 -18
  313. data/lib/ecoportal/api/graphql/mutation/location_structure.rb +13 -13
  314. data/lib/ecoportal/api/graphql/mutation/page/approve_review_task.rb +1 -1
  315. data/lib/ecoportal/api/graphql/mutation/page/archive.rb +40 -40
  316. data/lib/ecoportal/api/graphql/mutation/page/batch_update_review_task.rb +1 -1
  317. data/lib/ecoportal/api/graphql/mutation/page/build_from_template.rb +50 -50
  318. data/lib/ecoportal/api/graphql/mutation/page/create_draft.rb +1 -1
  319. data/lib/ecoportal/api/graphql/mutation/page/create_from_template.rb +43 -43
  320. data/lib/ecoportal/api/graphql/mutation/page/delete_draft.rb +1 -1
  321. data/lib/ecoportal/api/graphql/mutation/page/publish_draft.rb +1 -1
  322. data/lib/ecoportal/api/graphql/mutation/page/reject_review_task.rb +1 -1
  323. data/lib/ecoportal/api/graphql/mutation/page/restart_review_task.rb +1 -1
  324. data/lib/ecoportal/api/graphql/mutation/page/unarchive.rb +40 -40
  325. data/lib/ecoportal/api/graphql/mutation/page/undo_review_task.rb +1 -1
  326. data/lib/ecoportal/api/graphql/mutation/page/update.rb +40 -40
  327. data/lib/ecoportal/api/graphql/mutation/page.rb +28 -28
  328. data/lib/ecoportal/api/graphql/mutation/preset_view/create.rb +35 -35
  329. data/lib/ecoportal/api/graphql/mutation/preset_view/destroy.rb +1 -1
  330. data/lib/ecoportal/api/graphql/mutation/preset_view/permission.rb +37 -37
  331. data/lib/ecoportal/api/graphql/mutation/preset_view/update.rb +35 -35
  332. data/lib/ecoportal/api/graphql/mutation/preset_view.rb +15 -15
  333. data/lib/ecoportal/api/graphql/mutation/register/create.rb +35 -35
  334. data/lib/ecoportal/api/graphql/mutation/register/destroy.rb +1 -1
  335. data/lib/ecoportal/api/graphql/mutation/register/update.rb +35 -35
  336. data/lib/ecoportal/api/graphql/mutation/register.rb +14 -14
  337. data/lib/ecoportal/api/graphql/mutation/template/create.rb +35 -3
  338. data/lib/ecoportal/api/graphql/mutation/template/update.rb +4 -2
  339. data/lib/ecoportal/api/graphql/mutation.rb +1 -0
  340. data/lib/ecoportal/api/graphql/payload/action/archive.rb +13 -13
  341. data/lib/ecoportal/api/graphql/payload/action/create.rb +13 -13
  342. data/lib/ecoportal/api/graphql/payload/action/update.rb +13 -13
  343. data/lib/ecoportal/api/graphql/payload/action.rb +14 -14
  344. data/lib/ecoportal/api/graphql/payload/ai_summary_generate.rb +12 -12
  345. data/lib/ecoportal/api/graphql/payload/contractor_entity/create.rb +13 -13
  346. data/lib/ecoportal/api/graphql/payload/contractor_entity/destroy.rb +12 -12
  347. data/lib/ecoportal/api/graphql/payload/contractor_entity/update.rb +12 -12
  348. data/lib/ecoportal/api/graphql/payload/images_upload.rb +14 -0
  349. data/lib/ecoportal/api/graphql/payload/kickstand/bulk_update_jobs.rb +2 -2
  350. data/lib/ecoportal/api/graphql/payload/kickstand/bulk_update_workflows.rb +2 -2
  351. data/lib/ecoportal/api/graphql/payload/location_structure/apply_commands.rb +51 -51
  352. data/lib/ecoportal/api/graphql/payload/location_structure/command_execution_result.rb +50 -50
  353. data/lib/ecoportal/api/graphql/payload/location_structure/draft/add_commands.rb +30 -30
  354. data/lib/ecoportal/api/graphql/payload/location_structure/draft/delete.rb +30 -30
  355. data/lib/ecoportal/api/graphql/payload/location_structure/draft/drop_bad_commands.rb +43 -43
  356. data/lib/ecoportal/api/graphql/payload/location_structure/draft/publish.rb +63 -63
  357. data/lib/ecoportal/api/graphql/payload/location_structure/draft.rb +18 -18
  358. data/lib/ecoportal/api/graphql/payload/location_structure.rb +14 -14
  359. data/lib/ecoportal/api/graphql/payload/ok_payload.rb +1 -1
  360. data/lib/ecoportal/api/graphql/payload/page/archive.rb +13 -13
  361. data/lib/ecoportal/api/graphql/payload/page/build_from_template.rb +13 -13
  362. data/lib/ecoportal/api/graphql/payload/page/create_from_template.rb +13 -13
  363. data/lib/ecoportal/api/graphql/payload/page/draft.rb +1 -1
  364. data/lib/ecoportal/api/graphql/payload/page/review_task.rb +1 -1
  365. data/lib/ecoportal/api/graphql/payload/page/unarchive.rb +13 -13
  366. data/lib/ecoportal/api/graphql/payload/page/update.rb +13 -13
  367. data/lib/ecoportal/api/graphql/payload/preset_view.rb +1 -1
  368. data/lib/ecoportal/api/graphql/payload/register.rb +1 -1
  369. data/lib/ecoportal/api/graphql/payload.rb +1 -0
  370. data/lib/ecoportal/api/graphql/query/action.rb +33 -33
  371. data/lib/ecoportal/api/graphql/query/action_categories.rb +53 -53
  372. data/lib/ecoportal/api/graphql/query/actions.rb +43 -43
  373. data/lib/ecoportal/api/graphql/query/contractor_entities.rb +53 -53
  374. data/lib/ecoportal/api/graphql/query/file_upload_signature.rb +76 -76
  375. data/lib/ecoportal/api/graphql/query/location_classifications.rb +39 -39
  376. data/lib/ecoportal/api/graphql/query/page_delta.rb +47 -47
  377. data/lib/ecoportal/api/graphql/query/pages.rb +59 -59
  378. data/lib/ecoportal/api/graphql/query/permissions.rb +1 -1
  379. data/lib/ecoportal/api/graphql/query/person_members.rb +76 -0
  380. data/lib/ecoportal/api/graphql/query/register_preset_views.rb +1 -1
  381. data/lib/ecoportal/api/graphql/query/register_preview_pages.rb +83 -83
  382. data/lib/ecoportal/api/graphql/query/template_change_log.rb +118 -0
  383. data/lib/ecoportal/api/graphql/query/templates.rb +53 -53
  384. data/lib/ecoportal/api/graphql/query.rb +2 -0
  385. data/lib/ecoportal/api/graphql_version.rb +1 -1
  386. data/lib/ecoportal/api-graphql.rb +10 -10
  387. metadata +45 -9
  388. data/README.md +0 -24
  389. data/lib/ecoportal/api/common/graphql/CLAUDE.md +0 -36
  390. data/lib/ecoportal/api/common/graphql/model/CLAUDE.md +0 -28
  391. data/lib/ecoportal/api/graphql/CLAUDE.md +0 -37
  392. data/lib/ecoportal/api/graphql/base/CLAUDE.md +0 -50
  393. data/lib/ecoportal/api/graphql/builder/CLAUDE.md +0 -65
@@ -1,28 +1,28 @@
1
- module Ecoportal
2
- module API
3
- class GraphQL
4
- module Error
5
- class LocationsError < Logic::BaseModel
6
- read_only!
7
-
8
- passthrough :type, :message
9
- passarray :conflictingIds
10
- embeds_many :validationErrors, klass: LocationsValidationError
11
-
12
- def empty?
13
- return false unless conflictingIds.empty?
14
-
15
- validationErrors.empty?
16
- end
17
-
18
- def any?
19
- !empty?
20
- end
21
- end
22
- end
23
- end
24
- end
25
- end
26
-
27
-
28
- require_relative 'locations_error/fetch_nested'
1
+ module Ecoportal
2
+ module API
3
+ class GraphQL
4
+ module Error
5
+ class LocationsError < Logic::BaseModel
6
+ read_only!
7
+
8
+ passthrough :type, :message
9
+ passarray :conflictingIds
10
+ embeds_many :validationErrors, klass: LocationsValidationError
11
+
12
+ def empty?
13
+ return false unless conflictingIds.empty?
14
+
15
+ validationErrors.empty?
16
+ end
17
+
18
+ def any?
19
+ !empty?
20
+ end
21
+ end
22
+ end
23
+ end
24
+ end
25
+ end
26
+
27
+
28
+ require_relative 'locations_error/fetch_nested'
@@ -1,20 +1,20 @@
1
- module Ecoportal
2
- module API
3
- class GraphQL
4
- module Error
5
- class LocationsValidationError < Logic::BaseModel
6
- read_only!
7
-
8
- passthrough :error, :message, :property
9
-
10
- def empty?
11
- return false unless error.nil?
12
- return false unless message.nil?
13
-
14
- property.nil?
15
- end
16
- end
17
- end
18
- end
19
- end
20
- end
1
+ module Ecoportal
2
+ module API
3
+ class GraphQL
4
+ module Error
5
+ class LocationsValidationError < Logic::BaseModel
6
+ read_only!
7
+
8
+ passthrough :error, :message, :property
9
+
10
+ def empty?
11
+ return false unless error.nil?
12
+ return false unless message.nil?
13
+
14
+ property.nil?
15
+ end
16
+ end
17
+ end
18
+ end
19
+ end
20
+ end
@@ -1,28 +1,28 @@
1
- module Ecoportal
2
- module API
3
- class GraphQL
4
- module Error
5
- class ValidationErrors < Logic::BaseModel
6
- include Enumerable
7
-
8
- passthrough :details
9
- passarray :fullMessages
10
-
11
- def empty?
12
- count < 1
13
- end
14
-
15
- def any?
16
- !empty?
17
- end
18
-
19
- def each(&block)
20
- return to_enum(:each) unless block
21
-
22
- fullMessages.each(&block)
23
- end
24
- end
25
- end
26
- end
27
- end
28
- end
1
+ module Ecoportal
2
+ module API
3
+ class GraphQL
4
+ module Error
5
+ class ValidationErrors < Logic::BaseModel
6
+ include Enumerable
7
+
8
+ passthrough :details
9
+ passarray :fullMessages
10
+
11
+ def empty?
12
+ count < 1
13
+ end
14
+
15
+ def any?
16
+ !empty?
17
+ end
18
+
19
+ def each(&block)
20
+ return to_enum(:each) unless block
21
+
22
+ fullMessages.each(&block)
23
+ end
24
+ end
25
+ end
26
+ end
27
+ end
28
+ end
@@ -1,12 +1,12 @@
1
- module Ecoportal
2
- module API
3
- class GraphQL
4
- module Error
5
- end
6
- end
7
- end
8
- end
9
-
10
- require_relative 'error/locations_validation_error'
11
- require_relative 'error/validation_errors'
12
- require_relative 'error/locations_error'
1
+ module Ecoportal
2
+ module API
3
+ class GraphQL
4
+ module Error
5
+ end
6
+ end
7
+ end
8
+ end
9
+
10
+ require_relative 'error/locations_validation_error'
11
+ require_relative 'error/validation_errors'
12
+ require_relative 'error/locations_error'
@@ -26,21 +26,38 @@ module Ecoportal
26
26
  # `X-ECOPORTAL-API-KEY` is needed here: every ecoPortal call is GraphQL, on the session
27
27
  # token this client already holds.
28
28
  #
29
- # Single file:
29
+ # ★ Extended 2026-09 with `#upload_image`/`#upload_all_images` — steps 1-2 above (the
30
+ # presign + S3 POST) are IDENTICAL for an Image Gallery image; only step 3 differs
31
+ # (`uploadImage` -> a `TempImage`, not `uploadFile` -> a `FileContainer`). Confirmed
32
+ # against the live ecoPortal server source (read-only, /tmp/work/ecoPortal) that an
33
+ # Image Gallery image is genuinely NOT a `FileContainer` — see
34
+ # `Mutation::Image::Upload`'s and `Base::Page::DataField::ImageGallery`'s own headers
35
+ # for the full evidence trail. `#presign_and_store!` is the shared internal path both
36
+ # `#upload_one` and `#upload_one_image` call; `#run_batch` is the shared batch-with-
37
+ # progress-callback loop both `#upload_all` and `#upload_all_images` call.
38
+ #
39
+ # Single file, FileContainer (File-type fields):
30
40
  # id = api.file_upload.upload('/path/report.pdf')
31
41
  # page.components.get_by_name('Report').file_container_ids = [id]
32
42
  #
33
- # Many files, concurrently, with per-file error isolation (nothing raises out):
43
+ # Single file, TempImage (Image Gallery fields):
44
+ # source_id = api.file_upload.upload_image('/path/photo.jpg')
45
+ # page.components.get_by_name('Site Photos').add_source_images([{source_id: source_id, file_name: 'photo.jpg'}])
46
+ #
47
+ # Many files, concurrently, with per-file error isolation (nothing raises out) — same
48
+ # shape for both flows:
34
49
  # results = api.file_upload.upload_all(paths, threads: 4) do |r|
35
50
  # puts r.success? ? "#{r.file} -> #{r.container_id}" : "#{r.file} FAILED: #{r.error}"
36
51
  # end
37
52
  # results.select(&:error?)
38
53
  #
39
- # Instrumentation / middleware — hooks fire per stage, per file:
54
+ # Instrumentation / middleware — hooks fire per stage, per file, for EITHER flow (the
55
+ # stage names are shared: `:register` fires once whether the registration mutation was
56
+ # `uploadFile` or `uploadImage`):
40
57
  # client = api.file_upload
41
58
  # client.on(:signature) { |creds| logger.info "presigned #{creds.endpoint}" }
42
59
  # client.on(:storage) { |key, response| logger.info "S3 #{response.code} #{key}" }
43
- # client.on(:register) { |payload| logger.info "container #{payload.item&.id}" }
60
+ # client.on(:register) { |payload| logger.info "registered #{payload.item&.id}" }
44
61
  class Client
45
62
  include Ecoportal::API::GraphQL::Concerns::Threadable
46
63
 
@@ -51,9 +68,10 @@ module Ecoportal
51
68
 
52
69
  STAGES = %i[signature storage register].freeze
53
70
  # Fallback only — the real value is a condition inside the returned policy.
54
- DEFAULT_ENCRYPTION = 'AES256'.freeze
55
- DEFAULT_MIME = 'application/octet-stream'.freeze
56
- MAX_THREADS = 8
71
+ DEFAULT_ENCRYPTION = 'AES256'.freeze
72
+ DEFAULT_MIME = 'application/octet-stream'.freeze
73
+ DEFAULT_IMAGE_TYPE = 'image_gallery'.freeze
74
+ MAX_THREADS = 8
57
75
 
58
76
  # One entry per input file. Mirrors `ecoportal-api-v2`'s
59
77
  # `S3::Files::BatchUpload::FileResult` so batch code reads the same in both stacks.
@@ -77,13 +95,36 @@ module Ecoportal
77
95
  end
78
96
  end
79
97
 
98
+ # Sibling to {Result} for the image-upload pipeline — same shape, different item
99
+ # (a `TempImage`, not a `FileContainer`).
100
+ ImageResult = Struct.new(:file) do
101
+ attr_accessor :key, :payload, :error
102
+
103
+ def error?
104
+ !error.nil?
105
+ end
106
+
107
+ def success?
108
+ !error? && !temp_image_id.nil?
109
+ end
110
+
111
+ def temp_image
112
+ payload&.item
113
+ end
114
+
115
+ def temp_image_id
116
+ temp_image&.id
117
+ end
118
+ end
119
+
80
120
  def initialize(graphql_client)
81
121
  @graphql = graphql_client
82
122
  @hooks = {}
83
123
  end
84
124
 
85
125
  # Register a stage hook. Called for every file, in that file's own thread — keep it
86
- # thread-safe (or wrap it in your own mutex).
126
+ # thread-safe (or wrap it in your own mutex). Fires identically for {#upload} and
127
+ # {#upload_image} — the STAGE names are shared between both flows.
87
128
  # @param stage [:signature, :storage, :register]
88
129
  def on(stage, &block)
89
130
  stage = stage.to_sym
@@ -102,33 +143,32 @@ module Ecoportal
102
143
  result.container_id
103
144
  end
104
145
 
146
+ # @return [String] the new `TempImage` id (the `sourceId` an Image Gallery
147
+ # `ImageInput` write needs — see `Base::Page::DataField::ImageGallery#
148
+ # add_source_images`).
149
+ # @raise [Error] on any failure — use {#upload_all_images} for non-raising per-file
150
+ # isolation.
151
+ def upload_image(file_path, **kargs)
152
+ result = upload_one_image(file_path, **kargs)
153
+ raise result.error if result.error?
154
+
155
+ result.temp_image_id
156
+ end
157
+
105
158
  # Uploads many files with bounded concurrency. Never raises for a single file: each
106
159
  # {Result} carries its own error, and the block is called as each finishes.
107
160
  #
108
161
  # @param threads [Integer] max concurrent uploads (`1` = inline, deterministic).
109
162
  # @return [Array<Result>] one per input file; order is not guaranteed when threaded.
110
163
  def upload_all(file_paths, threads: 4, **kargs, &block)
111
- files = Array(file_paths).flatten.compact
112
- max = threads.to_i.clamp(1, MAX_THREADS)
113
- results = []
114
- spawned = []
115
-
116
- # Presign ONCE for the batch (the policy is time-boxed but reusable) and warm it
117
- # here so N threads don't race for the first one.
118
- credentials
119
-
120
- with_preserved_thread_globals do
121
- files.each do |file|
122
- new_thread(spawned, max: max) do
123
- result = upload_one(file, **kargs)
124
- mutex(:results).synchronize { results << result }
125
- block&.call(result)
126
- end
127
- end
128
- end
164
+ run_batch(file_paths, threads: threads, on_result: block) { |file| upload_one(file, **kargs) }
165
+ end
129
166
 
130
- spawned.each(&:join)
131
- results
167
+ # Sibling to {#upload_all} for the image-upload pipeline — identical concurrency,
168
+ # isolation and progress-callback semantics.
169
+ # @return [Array<ImageResult>]
170
+ def upload_all_images(file_paths, threads: 4, **kargs, &block)
171
+ run_batch(file_paths, threads: threads, on_result: block) { |file| upload_one_image(file, **kargs) }
132
172
  end
133
173
 
134
174
  # Force the next upload to presign again (e.g. after a policy expiry).
@@ -141,13 +181,10 @@ module Ecoportal
141
181
 
142
182
  def upload_one(file_path, location_ids: nil, tags: nil, container_id: nil)
143
183
  Result.new(file_path).tap do |result|
144
- raise MissingLocalFile, "no such file: #{file_path}" unless ::File.file?(file_path)
145
-
146
- creds = credentials
147
- result.key = storage_key(creds, file_path)
148
- store!(creds, result.key, file_path)
184
+ _creds, key = presign_and_store!(file_path)
185
+ result.key = key
149
186
  result.payload = register(
150
- file_path, result.key,
187
+ file_path, key,
151
188
  location_ids: location_ids, tags: tags, container_id: container_id
152
189
  )
153
190
  rescue StandardError => e
@@ -155,6 +192,61 @@ module Ecoportal
155
192
  end
156
193
  end
157
194
 
195
+ def upload_one_image(file_path, type: DEFAULT_IMAGE_TYPE, id: nil, import: true)
196
+ ImageResult.new(file_path).tap do |result|
197
+ _creds, key = presign_and_store!(file_path)
198
+ result.key = key
199
+ result.payload = register_image(file_path, key, type: type, id: id, import: import)
200
+ rescue StandardError => e
201
+ result.error = e
202
+ end
203
+ end
204
+
205
+ # Shared by BOTH flows: presign (memoised per batch), build a collision-proof S3
206
+ # key, and the multipart POST itself. Only the THIRD step (the registration
207
+ # mutation — `uploadFile` vs `uploadImage`) differs between {#upload_one} and
208
+ # {#upload_one_image}.
209
+ # @return [Array(Query::FileUploadSignature::SignatureResponse, String)] the
210
+ # credentials used and the S3 key the file was stored under.
211
+ def presign_and_store!(file_path)
212
+ raise MissingLocalFile, "no such file: #{file_path}" unless ::File.file?(file_path)
213
+
214
+ creds = credentials
215
+ key = storage_key(creds, file_path)
216
+ store!(creds, key, file_path)
217
+ [creds, key]
218
+ end
219
+
220
+ # Shared by {#upload_all}/{#upload_all_images}: bounded-concurrency loop, presign-
221
+ # once-per-batch, per-file error isolation, and a progress callback fired as each
222
+ # result lands (not deferred to the end). `upload_one` (the block) is the only thing
223
+ # that differs between the two callers.
224
+ # @yieldparam file_path [String]
225
+ # @yieldreturn [Result, ImageResult]
226
+ def run_batch(file_paths, threads:, on_result: nil)
227
+ files = Array(file_paths).flatten.compact
228
+ max = threads.to_i.clamp(1, MAX_THREADS)
229
+ results = []
230
+ spawned = []
231
+
232
+ # Presign ONCE for the batch (the policy is time-boxed but reusable) and warm it
233
+ # here so N threads don't race for the first one.
234
+ credentials
235
+
236
+ with_preserved_thread_globals do
237
+ files.each do |file|
238
+ new_thread(spawned, max: max) do
239
+ result = yield(file)
240
+ mutex(:results).synchronize { results << result }
241
+ on_result&.call(result)
242
+ end
243
+ end
244
+ end
245
+
246
+ spawned.each(&:join)
247
+ results
248
+ end
249
+
158
250
  # Memoised behind a mutex so a batch presigns once, not once per thread.
159
251
  def credentials
160
252
  mutex(:credentials).synchronize do
@@ -167,7 +259,8 @@ module Ecoportal
167
259
  # `uploads/<userId>/<epoch-ms>-<token>-/<basename>` — the shape the web client uses.
168
260
  # That stamp+token segment is what stops same-named files colliding: the previous
169
261
  # implementation concatenated `upload_prefix + filename`, so two uploads of
170
- # `report.pdf` overwrote each other in the bucket.
262
+ # `report.pdf` overwrote each other in the bucket. Shared by BOTH flows — an image
263
+ # upload needs the identical collision-proofing.
171
264
  def storage_key(creds, file_path)
172
265
  stamp = (Time.now.to_f * 1000).to_i
173
266
  "#{creds.upload_prefix}#{stamp}-#{SecureRandom.alphanumeric(20)}-/#{::File.basename(file_path)}"
@@ -224,6 +317,18 @@ module Ecoportal
224
317
  payload
225
318
  end
226
319
 
320
+ def register_image(file_path, key, type:, id:, import:)
321
+ payload = Mutation::Image::Upload.new(@graphql.client).query(
322
+ key: key, type: type, id: id, import: import
323
+ )
324
+ fire(:register, payload)
325
+
326
+ raise RegistrationFailed, "uploadImage failed for #{::File.basename(file_path)}: #{payload.error_doc}" if payload.error?
327
+ raise RegistrationFailed, "uploadImage returned no item for #{::File.basename(file_path)}" unless payload.item&.id
328
+
329
+ payload
330
+ end
331
+
227
332
  # The bucket policy dictates the encryption header, so echo it instead of assuming:
228
333
  # the policy is base64 JSON whose `conditions` carry `x-amz-server-side-encryption`.
229
334
  def encryption(creds)
@@ -1,10 +1,10 @@
1
- module Ecoportal
2
- module API
3
- class GraphQL
4
- module FileUpload
5
- end
6
- end
7
- end
8
- end
9
-
10
- require_relative 'file_upload/client'
1
+ module Ecoportal
2
+ module API
3
+ class GraphQL
4
+ module FileUpload
5
+ end
6
+ end
7
+ end
8
+ end
9
+
10
+ require_relative 'file_upload/client'
@@ -1,65 +1,65 @@
1
- module Ecoportal
2
- module API
3
- class GraphQL
4
- class Fragment
5
- fragment :Action, <<~GRAPHQL
6
- fragment Action on Action {
7
- id
8
- altId
9
- actionCategory {
10
- name
11
- value
12
- }
13
- actionCategoryId
14
- standaloneAction
15
- status
16
- relativeStatus
17
- archived
18
- locations {
19
- id
20
- name
21
- objectId
22
- }
23
- name
24
- description
25
- assignedTo {
26
- id
27
- name
28
- email
29
- }
30
- createdAt {
31
- dateTime
32
- timeZone
33
- }
34
- updatedAt {
35
- dateTime
36
- timeZone
37
- }
38
- dueDate {
39
- dateTime
40
- timeZone
41
- }
42
- completedAt {
43
- dateTime
44
- timeZone
45
- }
46
- completer {
47
- name
48
- email
49
- }
50
- linkedResources {
51
- id
52
- page {
53
- ... on BasePageInterface {
54
- id
55
- name
56
- uid
57
- }
58
- }
59
- }
60
- }
61
- GRAPHQL
62
- end
63
- end
64
- end
65
- end
1
+ module Ecoportal
2
+ module API
3
+ class GraphQL
4
+ class Fragment
5
+ fragment :Action, <<~GRAPHQL
6
+ fragment Action on Action {
7
+ id
8
+ altId
9
+ actionCategory {
10
+ name
11
+ value
12
+ }
13
+ actionCategoryId
14
+ standaloneAction
15
+ status
16
+ relativeStatus
17
+ archived
18
+ locations {
19
+ id
20
+ name
21
+ objectId
22
+ }
23
+ name
24
+ description
25
+ assignedTo {
26
+ id
27
+ name
28
+ email
29
+ }
30
+ createdAt {
31
+ dateTime
32
+ timeZone
33
+ }
34
+ updatedAt {
35
+ dateTime
36
+ timeZone
37
+ }
38
+ dueDate {
39
+ dateTime
40
+ timeZone
41
+ }
42
+ completedAt {
43
+ dateTime
44
+ timeZone
45
+ }
46
+ completer {
47
+ name
48
+ email
49
+ }
50
+ linkedResources {
51
+ id
52
+ page {
53
+ ... on BasePageInterface {
54
+ id
55
+ name
56
+ uid
57
+ }
58
+ }
59
+ }
60
+ }
61
+ GRAPHQL
62
+ end
63
+ end
64
+ end
65
+ end
@@ -1,17 +1,17 @@
1
- module Ecoportal
2
- module API
3
- class GraphQL
4
- class Fragment
5
- fragment :ActionCategory, <<~GRAPHQL
6
- fragment ActionCategory on Category {
7
- id
8
- name
9
- value
10
- archived
11
- weight
12
- }
13
- GRAPHQL
14
- end
15
- end
16
- end
17
- end
1
+ module Ecoportal
2
+ module API
3
+ class GraphQL
4
+ class Fragment
5
+ fragment :ActionCategory, <<~GRAPHQL
6
+ fragment ActionCategory on Category {
7
+ id
8
+ name
9
+ value
10
+ archived
11
+ weight
12
+ }
13
+ GRAPHQL
14
+ end
15
+ end
16
+ end
17
+ end
@@ -1,20 +1,20 @@
1
- module Ecoportal
2
- module API
3
- class GraphQL
4
- class Fragment
5
- fragment :ContractorEntity, <<~GRAPHQL
6
- fragment ContractorEntity on ContractorEntity {
7
- id
8
- externalId
9
- name
10
- schemaId
11
- active
12
- approved
13
- associatedPeopleIds
14
- leadContractorIds
15
- }
16
- GRAPHQL
17
- end
18
- end
19
- end
20
- end
1
+ module Ecoportal
2
+ module API
3
+ class GraphQL
4
+ class Fragment
5
+ fragment :ContractorEntity, <<~GRAPHQL
6
+ fragment ContractorEntity on ContractorEntity {
7
+ id
8
+ externalId
9
+ name
10
+ schemaId
11
+ active
12
+ approved
13
+ associatedPeopleIds
14
+ leadContractorIds
15
+ }
16
+ GRAPHQL
17
+ end
18
+ end
19
+ end
20
+ end