ecoportal-api-graphql 1.3.16 → 2.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 (149) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +384 -6
  3. data/lib/ecoportal/api/common/graphql/model/diffable/leaf_diff_service.rb +97 -0
  4. data/lib/ecoportal/api/common/graphql/model/diffable.rb +1 -0
  5. data/lib/ecoportal/api/graphql/base/action.rb +1 -1
  6. data/lib/ecoportal/api/graphql/base/action_event.rb +23 -0
  7. data/lib/ecoportal/api/graphql/base/action_event_page.rb +16 -0
  8. data/lib/ecoportal/api/graphql/base/activity.rb +38 -0
  9. data/lib/ecoportal/api/graphql/base/activity_log.rb +38 -0
  10. data/lib/ecoportal/api/graphql/base/ai_summary_version.rb +12 -7
  11. data/lib/ecoportal/api/graphql/base/auth_log.rb +24 -0
  12. data/lib/ecoportal/api/graphql/base/authorization_result.rb +20 -0
  13. data/lib/ecoportal/api/graphql/base/contractor_entity/member_changes.rb +17 -5
  14. data/lib/ecoportal/api/graphql/base/file_container.rb +12 -4
  15. data/lib/ecoportal/api/graphql/base/location_classification_type.rb +2 -0
  16. data/lib/ecoportal/api/graphql/base/location_structure.rb +3 -0
  17. data/lib/ecoportal/api/graphql/base/minimal_dashboard.rb +25 -0
  18. data/lib/ecoportal/api/graphql/base/organization.rb +2 -0
  19. data/lib/ecoportal/api/graphql/base/page/data_field/contractor_entities.rb +26 -3
  20. data/lib/ecoportal/api/graphql/base/page/data_field/file_field.rb +47 -8
  21. data/lib/ecoportal/api/graphql/base/page/data_field/image_gallery.rb +5 -2
  22. data/lib/ecoportal/api/graphql/base/page/data_field/people.rb +50 -12
  23. data/lib/ecoportal/api/graphql/base/page/data_field.rb +12 -18
  24. data/lib/ecoportal/api/graphql/base/permissions.rb +15 -0
  25. data/lib/ecoportal/api/graphql/base/person_member_changelog.rb +23 -0
  26. data/lib/ecoportal/api/graphql/base/preset_view.rb +136 -1
  27. data/lib/ecoportal/api/graphql/base/register.rb +5 -0
  28. data/lib/ecoportal/api/graphql/base.rb +9 -0
  29. data/lib/ecoportal/api/graphql/builder/contractor_entity.rb +10 -0
  30. data/lib/ecoportal/api/graphql/builder/page.rb +0 -16
  31. data/lib/ecoportal/api/graphql/builder/template.rb +18 -0
  32. data/lib/ecoportal/api/graphql/compat/pages.rb +7 -2
  33. data/lib/ecoportal/api/graphql/compat/response.rb +14 -0
  34. data/lib/ecoportal/api/graphql/concerns/threadable.rb +58 -0
  35. data/lib/ecoportal/api/graphql/concerns.rb +1 -0
  36. data/lib/ecoportal/api/graphql/connection/action.rb +1 -1
  37. data/lib/ecoportal/api/graphql/connection/action_category.rb +1 -1
  38. data/lib/ecoportal/api/graphql/connection/activity.rb +11 -0
  39. data/lib/ecoportal/api/graphql/connection/activity_log.rb +11 -0
  40. data/lib/ecoportal/api/graphql/connection/auth_log.rb +11 -0
  41. data/lib/ecoportal/api/graphql/connection/contractor_entity.rb +1 -1
  42. data/lib/ecoportal/api/graphql/connection/minimal_dashboard.rb +11 -0
  43. data/lib/ecoportal/api/graphql/connection/page.rb +1 -1
  44. data/lib/ecoportal/api/graphql/connection/pages_workflow_command.rb +1 -1
  45. data/lib/ecoportal/api/graphql/connection/person_member.rb +1 -1
  46. data/lib/ecoportal/api/graphql/connection/person_member_changelog.rb +11 -0
  47. data/lib/ecoportal/api/graphql/connection/preview_page.rb +1 -1
  48. data/lib/ecoportal/api/graphql/connection.rb +5 -0
  49. data/lib/ecoportal/api/graphql/diff/pairing/signals.rb +21 -1
  50. data/lib/ecoportal/api/graphql/file_upload/client.rb +199 -140
  51. data/lib/ecoportal/api/graphql/fragment/activity.rb +84 -0
  52. data/lib/ecoportal/api/graphql/fragment/activity_log.rb +75 -0
  53. data/lib/ecoportal/api/graphql/fragment/auth_log.rb +29 -0
  54. data/lib/ecoportal/api/graphql/fragment/authorization_result.rb +14 -0
  55. data/lib/ecoportal/api/graphql/fragment/location_node.rb +1 -0
  56. data/lib/ecoportal/api/graphql/fragment/minimal_dashboard.rb +31 -0
  57. data/lib/ecoportal/api/graphql/fragment/pages/common_page_union.rb +21 -0
  58. data/lib/ecoportal/api/graphql/fragment/permissions.rb +98 -0
  59. data/lib/ecoportal/api/graphql/fragment/person_member_changelog.rb +33 -0
  60. data/lib/ecoportal/api/graphql/fragment.rb +7 -0
  61. data/lib/ecoportal/api/graphql/input/action/update.rb +12 -0
  62. data/lib/ecoportal/api/graphql/input/contractor_entity/manager_settings.rb +20 -0
  63. data/lib/ecoportal/api/graphql/input/contractor_entity/update.rb +6 -27
  64. data/lib/ecoportal/api/graphql/input/contractor_entity.rb +1 -0
  65. data/lib/ecoportal/api/graphql/input/date_range.rb +16 -0
  66. data/lib/ecoportal/api/graphql/input/location_structure/apply_commands.rb +2 -2
  67. data/lib/ecoportal/api/graphql/input/location_structure/draft/add_commands.rb +2 -2
  68. data/lib/ecoportal/api/graphql/input/location_structure/update_command.rb +6 -2
  69. data/lib/ecoportal/api/graphql/input/preset_view/update.rb +16 -1
  70. data/lib/ecoportal/api/graphql/input/workflow_command/add_checklist_field_item.rb +19 -0
  71. data/lib/ecoportal/api/graphql/input/workflow_command/add_smart_fill_config.rb +23 -0
  72. data/lib/ecoportal/api/graphql/input/workflow_command/add_stage.rb +3 -2
  73. data/lib/ecoportal/api/graphql/input/workflow_command/add_viewable_field.rb +45 -0
  74. data/lib/ecoportal/api/graphql/input/workflow_command/archive_public_config.rb +19 -0
  75. data/lib/ecoportal/api/graphql/input/workflow_command/create_public_config.rb +19 -0
  76. data/lib/ecoportal/api/graphql/input/workflow_command/edit_checklist_field_item.rb +19 -0
  77. data/lib/ecoportal/api/graphql/input/workflow_command/edit_field_configuration.rb +12 -2
  78. data/lib/ecoportal/api/graphql/input/workflow_command/edit_public_config.rb +19 -0
  79. data/lib/ecoportal/api/graphql/input/workflow_command/edit_smart_fill_config.rb +21 -0
  80. data/lib/ecoportal/api/graphql/input/workflow_command/edit_template_advanced_settings.rb +19 -0
  81. data/lib/ecoportal/api/graphql/input/workflow_command/edit_template_basic_settings.rb +27 -0
  82. data/lib/ecoportal/api/graphql/input/workflow_command/edit_template_container_uid.rb +45 -0
  83. data/lib/ecoportal/api/graphql/input/workflow_command/{edit_page_creator_permissions.rb → edit_template_creator_permissions.rb} +3 -2
  84. data/lib/ecoportal/api/graphql/input/workflow_command/edit_template_descriptions.rb +19 -0
  85. data/lib/ecoportal/api/graphql/input/workflow_command/field_config/action_list.rb +31 -0
  86. data/lib/ecoportal/api/graphql/input/workflow_command/field_config/cross_reference.rb +3 -1
  87. data/lib/ecoportal/api/graphql/input/workflow_command/field_config/date.rb +15 -2
  88. data/lib/ecoportal/api/graphql/input/workflow_command/field_config/file.rb +21 -0
  89. data/lib/ecoportal/api/graphql/input/workflow_command/field_config/image_gallery.rb +3 -2
  90. data/lib/ecoportal/api/graphql/input/workflow_command/field_config/people.rb +27 -3
  91. data/lib/ecoportal/api/graphql/input/workflow_command/field_config/plain_text.rb +3 -2
  92. data/lib/ecoportal/api/graphql/input/workflow_command/field_config/rich_text.rb +3 -2
  93. data/lib/ecoportal/api/graphql/input/workflow_command/field_config/select.rb +3 -2
  94. data/lib/ecoportal/api/graphql/input/workflow_command/move_field.rb +3 -2
  95. data/lib/ecoportal/api/graphql/input/workflow_command/move_viewable_field.rb +33 -0
  96. data/lib/ecoportal/api/graphql/input/workflow_command/remove_checklist_field_item.rb +19 -0
  97. data/lib/ecoportal/api/graphql/input/workflow_command/remove_smart_fill_config.rb +19 -0
  98. data/lib/ecoportal/api/graphql/input/workflow_command/remove_viewable_field.rb +21 -0
  99. data/lib/ecoportal/api/graphql/input/workflow_command/reorder_forces.rb +3 -2
  100. data/lib/ecoportal/api/graphql/input/workflow_command/reorder_section.rb +3 -2
  101. data/lib/ecoportal/api/graphql/input/workflow_command.rb +43 -5
  102. data/lib/ecoportal/api/graphql/input.rb +1 -0
  103. data/lib/ecoportal/api/graphql/interface/base_page.rb +36 -3
  104. data/lib/ecoportal/api/graphql/interface/location_structure/command.rb +2 -1
  105. data/lib/ecoportal/api/graphql/logic/connection.rb +17 -0
  106. data/lib/ecoportal/api/graphql/logic/input.rb +127 -0
  107. data/lib/ecoportal/api/graphql/model/action_event.rb +14 -0
  108. data/lib/ecoportal/api/graphql/model/action_event_page.rb +10 -0
  109. data/lib/ecoportal/api/graphql/model/activity.rb +14 -0
  110. data/lib/ecoportal/api/graphql/model/activity_log.rb +31 -0
  111. data/lib/ecoportal/api/graphql/model/auth_log.rb +11 -0
  112. data/lib/ecoportal/api/graphql/model/authorization_result.rb +12 -0
  113. data/lib/ecoportal/api/graphql/model/minimal_dashboard.rb +14 -0
  114. data/lib/ecoportal/api/graphql/model/organization.rb +27 -0
  115. data/lib/ecoportal/api/graphql/model/permissions.rb +179 -0
  116. data/lib/ecoportal/api/graphql/model/person_member.rb +7 -0
  117. data/lib/ecoportal/api/graphql/model/person_member_changelog.rb +15 -0
  118. data/lib/ecoportal/api/graphql/model.rb +9 -0
  119. data/lib/ecoportal/api/graphql/mutation/ai_summary/generate.rb +20 -10
  120. data/lib/ecoportal/api/graphql/mutation/ai_summary/submit_feedback.rb +25 -10
  121. data/lib/ecoportal/api/graphql/mutation/contractor_entity/update_manager_settings.rb +37 -0
  122. data/lib/ecoportal/api/graphql/mutation/contractor_entity.rb +1 -0
  123. data/lib/ecoportal/api/graphql/mutation/file_container/upload.rb +78 -0
  124. data/lib/ecoportal/api/graphql/mutation/file_container.rb +15 -0
  125. data/lib/ecoportal/api/graphql/mutation/template/update_related_page.rb +79 -0
  126. data/lib/ecoportal/api/graphql/mutation/template.rb +1 -0
  127. data/lib/ecoportal/api/graphql/mutation.rb +1 -1
  128. data/lib/ecoportal/api/graphql/payload/contractor_entity/manager_settings.rb +20 -0
  129. data/lib/ecoportal/api/graphql/payload/contractor_entity.rb +1 -0
  130. data/lib/ecoportal/api/graphql/payload/template/update_related_page.rb +15 -0
  131. data/lib/ecoportal/api/graphql/payload/template.rb +1 -0
  132. data/lib/ecoportal/api/graphql/payload/upload.rb +12 -0
  133. data/lib/ecoportal/api/graphql/payload.rb +1 -0
  134. data/lib/ecoportal/api/graphql/query/activity_logs.rb +78 -0
  135. data/lib/ecoportal/api/graphql/query/auth_logs.rb +51 -0
  136. data/lib/ecoportal/api/graphql/query/dashboard_search.rb +57 -0
  137. data/lib/ecoportal/api/graphql/query/location_structure.rb +2 -0
  138. data/lib/ecoportal/api/graphql/query/location_structures.rb +2 -0
  139. data/lib/ecoportal/api/graphql/query/page.rb +6 -1
  140. data/lib/ecoportal/api/graphql/query/page_activities.rb +56 -0
  141. data/lib/ecoportal/api/graphql/query/permissions.rb +35 -0
  142. data/lib/ecoportal/api/graphql/query/person_member_changelogs.rb +53 -0
  143. data/lib/ecoportal/api/graphql/query.rb +6 -0
  144. data/lib/ecoportal/api/graphql_version.rb +1 -1
  145. metadata +73 -12
  146. data/lib/ecoportal/api/graphql/input/workflow_command/edit_page.rb +0 -28
  147. data/lib/ecoportal/api/graphql/mutation/smart_fill/generate.rb +0 -36
  148. data/lib/ecoportal/api/graphql/mutation/smart_fill/submit_feedback.rb +0 -40
  149. data/lib/ecoportal/api/graphql/mutation/smart_fill.rb +0 -13
@@ -92,6 +92,16 @@ module Ecoportal
92
92
  creator { name email }
93
93
  state
94
94
  archived
95
+ # Cross-version template identity. `template` is non-null only on template pages
96
+ # (`BasePageInterface.template: Template`), so this stays nil for records.
97
+ # `templateContainerUid` is the SERIES key: many versions may carry the same uid,
98
+ # but only one may be published (`active: true`) per organization at a time —
99
+ # publishing another with the same uid unpublishes the incumbent. See
100
+ # `.ai-assistance/code/ecoPortal_architecture/02_data_model.md`.
101
+ template @skip(if: $only_content) {
102
+ templateContainerUid
103
+ active
104
+ }
95
105
  }
96
106
 
97
107
  fragment sectionsFragment on Stage {
@@ -119,6 +129,16 @@ module Ecoportal
119
129
  __typename
120
130
  id @skip(if: $only_content)
121
131
  label
132
+ # Field-configuration `description` (the hidden per-field note). Read-only from
133
+ # here — the ONLY writer is the `editFieldConfiguration` workflow command
134
+ # (`WorkflowEditFieldConfigurationInput.description`); `DataFieldInput` and its
135
+ # per-type members carry no description, so `updatePage` cannot set it.
136
+ #
137
+ # Integrations use it as a pseudo external-id on fields (we do so on templates;
138
+ # M&S do so on page instances — confirmed working on instances with a
139
+ # non-superuser service account, 2026-07-31). Fetched by default so those
140
+ # integrations can read it back.
141
+ description @skip(if: $only_content)
122
142
  genomeSignature @skip(if: $only_content)
123
143
  deindex @include(if: $content)
124
144
  linkedFieldConfig @skip(if: $only_content) {
@@ -232,6 +252,7 @@ module Ecoportal
232
252
  fragment fileField on File {
233
253
  required @skip(if: $only_content)
234
254
  items @include(if: $content) {
255
+ id
235
256
  fileContainer { ...fileContainerAttrs }
236
257
  }
237
258
  }
@@ -0,0 +1,98 @@
1
+ module Ecoportal
2
+ module API
3
+ class GraphQL
4
+ class Fragment
5
+ # Selects every canXXX permission on the Permissions type, spreading :AuthorizationResult
6
+ # ({ value message }) for each. Requires the :AuthorizationResult fragment to be assembled
7
+ # alongside (Fragment.assemble(:Permissions, :AuthorizationResult)).
8
+ fragment :Permissions, <<~GRAPHQL
9
+ fragment Permissions on Permissions {
10
+ actionCanCreateStandalone { ...AuthorizationResult }
11
+ actionCanIndex { ...AuthorizationResult }
12
+ alertNotificationCanAccessBroadcastNotifications { ...AuthorizationResult }
13
+ alertNotificationCanCreate { ...AuthorizationResult }
14
+ alertNotificationCanIndex { ...AuthorizationResult }
15
+ canAccessAdminTools { ...AuthorizationResult }
16
+ canAccessPeopleManager { ...AuthorizationResult }
17
+ canDeleteActionCategories { ...AuthorizationResult }
18
+ canIndex { ...AuthorizationResult }
19
+ canListAttachablePersonMembers { ...AuthorizationResult }
20
+ canManageActionCategories { ...AuthorizationResult }
21
+ canManageStandaloneActionsPermissions { ...AuthorizationResult }
22
+ canResetActionsCounter { ...AuthorizationResult }
23
+ canUpload { ...AuthorizationResult }
24
+ contractorEntityCanAccessContractorManager { ...AuthorizationResult }
25
+ contractorEntityCanAttach { ...AuthorizationResult }
26
+ contractorEntityCanCreate { ...AuthorizationResult }
27
+ contractorEntityCanDestroy { ...AuthorizationResult }
28
+ contractorEntityCanEdit { ...AuthorizationResult }
29
+ contractorEntityCanEditLinkedUsers { ...AuthorizationResult }
30
+ contractorEntityCanIndex { ...AuthorizationResult }
31
+ contractorEntityCanManageParentContractors { ...AuthorizationResult }
32
+ contractorEntityCanManageSubcontractors { ...AuthorizationResult }
33
+ crossReferenceReportsCanIndex { ...AuthorizationResult }
34
+ dashboardCanManage { ...AuthorizationResult }
35
+ dataSetsCanIndex { ...AuthorizationResult }
36
+ dataSpaceCanShow { ...AuthorizationResult }
37
+ dataViewsCanIndex { ...AuthorizationResult }
38
+ emailReportCanConfigureSmartReport { ...AuthorizationResult }
39
+ filesCanIndex { ...AuthorizationResult }
40
+ filesCanUpload { ...AuthorizationResult }
41
+ generatedPageFilterCanCreate { ...AuthorizationResult }
42
+ generatedPageFilterCanUseSmartQuery { ...AuthorizationResult }
43
+ hasFileAbilityToDownload { ...AuthorizationResult }
44
+ locationClassificationsCanCreate { ...AuthorizationResult }
45
+ locationClassificationsCanUpdate { ...AuthorizationResult }
46
+ locationStructuresCanAccess { ...AuthorizationResult }
47
+ locationStructuresCanAdministrate { ...AuthorizationResult }
48
+ locationStructuresCanAiGenerateStructure { ...AuthorizationResult }
49
+ locationStructuresCanCreate { ...AuthorizationResult }
50
+ locationStructuresCanManage { ...AuthorizationResult }
51
+ locationStructuresCanManageSftpIntegration { ...AuthorizationResult }
52
+ locationStructuresCanPublish { ...AuthorizationResult }
53
+ locationStructuresCanRead { ...AuthorizationResult }
54
+ locationStructuresCanScheduleUpdate { ...AuthorizationResult }
55
+ locationStructuresCanUpdate { ...AuthorizationResult }
56
+ organizationCanViewSettings { ...AuthorizationResult }
57
+ pageAiSummaryCanAccess { ...AuthorizationResult }
58
+ pageCanListDrafts { ...AuthorizationResult }
59
+ pageCanRestore { ...AuthorizationResult }
60
+ pageCanUseDrafts { ...AuthorizationResult }
61
+ pageSmartAssistantCanChat { ...AuthorizationResult }
62
+ personSchemaCanAccessManager { ...AuthorizationResult }
63
+ publicTemplatesCanCopyLink { ...AuthorizationResult }
64
+ publicTemplatesCanIndex { ...AuthorizationResult }
65
+ publicTemplatesCanListEntries { ...AuthorizationResult }
66
+ publicTemplatesCanManage { ...AuthorizationResult }
67
+ registerAssistantCanChat { ...AuthorizationResult }
68
+ registerCanAccessRegisterTools { ...AuthorizationResult }
69
+ registerCanCreate { ...AuthorizationResult }
70
+ registerCanLimitTemplates { ...AuthorizationResult }
71
+ scimIntegrationCanAddCodeHooks { ...AuthorizationResult }
72
+ scimIntegrationCanCreate { ...AuthorizationResult }
73
+ scimIntegrationCanDestroy { ...AuthorizationResult }
74
+ scimIntegrationCanGenerateApiKey { ...AuthorizationResult }
75
+ scimIntegrationCanIndex { ...AuthorizationResult }
76
+ scimIntegrationCanShow { ...AuthorizationResult }
77
+ scimIntegrationCanShowLogs { ...AuthorizationResult }
78
+ scimIntegrationCanUpdate { ...AuthorizationResult }
79
+ spatialCanUpdateLocationNodeGeojson { ...AuthorizationResult }
80
+ structuresCanIndex { ...AuthorizationResult }
81
+ templateCanRestore { ...AuthorizationResult }
82
+ userAccessLogsCanShow { ...AuthorizationResult }
83
+ userCanAccessAdminArea { ...AuthorizationResult }
84
+ userCanAccessPageCreationTools { ...AuthorizationResult }
85
+ visitorLogCanAdminCheckIn { ...AuthorizationResult }
86
+ visitorLogCanEdit { ...AuthorizationResult }
87
+ visitorLogCanManage { ...AuthorizationResult }
88
+ visitorLogCanShow { ...AuthorizationResult }
89
+ visitorManagementCanAccessVisitorManager { ...AuthorizationResult }
90
+ visitorManagementCanIndex { ...AuthorizationResult }
91
+ webhooksCanManageSubscriptions { ...AuthorizationResult }
92
+ webhooksCanViewSubscriptions { ...AuthorizationResult }
93
+ }
94
+ GRAPHQL
95
+ end
96
+ end
97
+ end
98
+ end
@@ -0,0 +1,33 @@
1
+ module Ecoportal
2
+ module API
3
+ class GraphQL
4
+ class Fragment
5
+ fragment :PersonMemberChangelog, <<~GRAPHQL
6
+ fragment PersonMemberChangelog on PersonMemberChangelog {
7
+ id
8
+ operation
9
+ accountOperation
10
+ personMemberId
11
+ apiKeyPrefix
12
+ changedByApi
13
+ humanReadableDifferences
14
+ createdAt {
15
+ dateTime
16
+ timeZone
17
+ }
18
+ personMember {
19
+ id
20
+ name
21
+ email
22
+ }
23
+ user {
24
+ id
25
+ email
26
+ name
27
+ }
28
+ }
29
+ GRAPHQL
30
+ end
31
+ end
32
+ end
33
+ end
@@ -35,6 +35,13 @@ require_relative 'fragment/page'
35
35
  require_relative 'fragment/pages'
36
36
  require_relative 'fragment/force'
37
37
  require_relative 'fragment/pages_workflow'
38
+ require_relative 'fragment/authorization_result'
39
+ require_relative 'fragment/permissions'
40
+ require_relative 'fragment/activity'
41
+ require_relative 'fragment/activity_log'
42
+ require_relative 'fragment/auth_log'
43
+ require_relative 'fragment/person_member_changelog'
44
+ require_relative 'fragment/minimal_dashboard'
38
45
  require_relative 'fragment/field_configuration'
39
46
  require_relative 'fragment/page_task'
40
47
  require_relative 'fragment/template'
@@ -4,8 +4,20 @@ module Ecoportal
4
4
  module Input
5
5
  module Action
6
6
  class Update < Ecoportal::API::GraphQL::Base::Action
7
+ extend Logic::Input::FullArrayFields
8
+
7
9
  passthrough :clientMutationId
8
10
  passthrough :updateMode
11
+
12
+ # Base::Action is `root!`, so its own `as_update` never emits its array fields — an
13
+ # unaugmented Action::Update produced nothing for changed id-lists. The macro gives it
14
+ # emission, reading the full current array directly from doc vs original_doc.
15
+ #
16
+ # Schema (live introspection 20260605, UpdateActionInput): these are plain `[ID!]`,
17
+ # NOT IdDiffInput — the server expects the COMPLETE array, not additions/removals
18
+ # deltas. Hence `full_array_fields`, not `id_diff_fields` (contrast ContractorEntity,
19
+ # whose associatedPeopleIds/leadContractorIds ARE IdDiffInput).
20
+ full_array_fields :assignedPersonMemberIds, :locationIds, :fileContainerIds
9
21
  end
10
22
  end
11
23
  end
@@ -0,0 +1,20 @@
1
+ module Ecoportal
2
+ module API
3
+ class GraphQL
4
+ module Input
5
+ module ContractorEntity
6
+ # Input for the `updateContractorManagerSettings` mutation (2026-07 schema;
7
+ # renamed from the removed `updateCmAutoApprovalsSettings` / CmAutoApprovalsSettingsInput,
8
+ # which this gem never modelled).
9
+ #
10
+ # `cmAutoApprovalsSettings` is a required AutoApprovalsInput
11
+ # ({ enabled:, approvalConditions: }); pass it as a Hash.
12
+ class ManagerSettings < Logic::Input
13
+ passthrough :cmAutoApprovalsSettings
14
+ passboolean :allowContractorAdminsToAddAdmins
15
+ end
16
+ end
17
+ end
18
+ end
19
+ end
20
+ end
@@ -4,35 +4,14 @@ module Ecoportal
4
4
  module Input
5
5
  module ContractorEntity
6
6
  class Update < Input::ContractorEntity::Create
7
- passthrough :clientMutationId
8
- class_resolver :id_diff_input, "Ecoportal::API::GraphQL::Input::IdDiff"
9
- embeds_one :associatedPeopleIds, klass: :id_diff_input
10
- embeds_one :leadContractorIds, klass: :id_diff_input
11
-
12
- ID_DIFF_FIELDS = %i[associatedPeopleIds leadContractorIds].freeze
13
-
14
- class << self
15
- # Overrides Logic::Input.from_model to reshape array fields into
16
- # IdDiffInput format: { additions: [...], removals: [...] }
17
- # Array fields are stripped from the flat diff, so we compare
18
- # doc vs original_doc directly rather than relying on the diff hash.
19
- def from_model(model, **kargs)
20
- diff = Logic::Input.from_model(model, **kargs)
7
+ extend Logic::Input::IdDiffFields
21
8
 
22
- ID_DIFF_FIELDS.each do |field|
23
- key = field.to_s
24
- current = Array(model.doc[key])
25
- original = Array(model.original_doc[key])
26
- next if current == original
27
-
28
- diff ||= {}
29
- diff[:id] ||= model.id
30
- diff[field] = { additions: current - original, removals: original - current }
31
- end
9
+ passthrough :clientMutationId
32
10
 
33
- diff
34
- end
35
- end
11
+ # `associatedPeopleIds` / `leadContractorIds` are exposed on UpdateContractorEntityInput
12
+ # as IdDiffInput { additions:, removals: }. The macro installs a `from_model` that
13
+ # computes each delta directly from the read model's doc vs original_doc arrays.
14
+ id_diff_fields :associatedPeopleIds, :leadContractorIds
36
15
  end
37
16
  end
38
17
  end
@@ -12,3 +12,4 @@ end
12
12
  require_relative 'contractor_entity/create'
13
13
  require_relative 'contractor_entity/destroy'
14
14
  require_relative 'contractor_entity/update'
15
+ require_relative 'contractor_entity/manager_settings'
@@ -0,0 +1,16 @@
1
+ module Ecoportal
2
+ module API
3
+ class GraphQL
4
+ module Input
5
+ # DateRange input for filtering time-bounded queries (e.g. the
6
+ # `dateFilter` arg of `activityLogs`).
7
+ # from: ISO8601DateTime
8
+ # to: ISO8601DateTime
9
+ # Pass as: { from: '2026-07-01T00:00:00Z', to: '2026-07-14T00:00:00Z' }
10
+ class DateRange < Logic::BaseModel
11
+ passthrough :from, :to
12
+ end
13
+ end
14
+ end
15
+ end
16
+ end
@@ -33,8 +33,8 @@ module Ecoportal
33
33
  Input::LocationStructure::InsertCommand.new
34
34
  when :update
35
35
  Input::LocationStructure::UpdateCommand.new
36
- when :reoder
37
- Input::LocationStructure::ReoderCommand.new
36
+ when :reorder
37
+ Input::LocationStructure::ReorderCommand.new
38
38
  else
39
39
  raise "Unknown command type: '#{type}'"
40
40
  end
@@ -34,8 +34,8 @@ module Ecoportal
34
34
  Input::LocationStructure::InsertCommand.new
35
35
  when :update
36
36
  Input::LocationStructure::UpdateCommand.new
37
- when :reoder
38
- Input::LocationStructure::ReoderCommand.new
37
+ when :reorder
38
+ Input::LocationStructure::ReorderCommand.new
39
39
  else
40
40
  raise "Unknown command type: '#{type}'"
41
41
  end
@@ -8,14 +8,18 @@ module Ecoportal
8
8
  passthrough :name, :newName
9
9
  passthrough :classificationIds, :newClassificationIds
10
10
 
11
+ # Effective name: the new value if one was set, otherwise the
12
+ # current value stored under +name+.
11
13
  def name
12
- super if newName.nil?
14
+ return doc["name"] if newName.nil?
13
15
 
14
16
  newName
15
17
  end
16
18
 
19
+ # Effective classification ids: the new value if one was set,
20
+ # otherwise the current value stored under +classificationIds+.
17
21
  def classificationIds
18
- super if newClassificationIds.empty?
22
+ return doc["classificationIds"] if newClassificationIds.nil? || newClassificationIds.empty?
19
23
 
20
24
  newClassificationIds
21
25
  end
@@ -7,7 +7,22 @@
7
7
  passkey :id
8
8
  passthrough :name, :sorter
9
9
  passboolean :preview
10
- passarray :fieldConfigs
10
+ # NOT a list: `UpdatePresetViewInput.fieldConfigs` is a (required)
11
+ # `FieldConfigurationOneToManyInput` — `{ additions:, deletions:, updates: }`.
12
+ # Only `CreatePresetViewInput` takes the plain `[FieldConfigurationInput!]!`.
13
+ passthrough :fieldConfigs
14
+
15
+ class << self
16
+ # The read model (Base::PresetView) exposes the collection as the
17
+ # `fieldConfigurations` LIST; this input takes it as the `fieldConfigs`
18
+ # one-to-many OBJECT. Base::PresetView owns the rename + reshape, so this
19
+ # explicit-converter seam (`as_input(target_class:)`, or a direct
20
+ # `.from_model`) stays in step with the implicit `model.as_input` one.
21
+ # The reshape is idempotent, so applying it on both is harmless.
22
+ def from_model(model, **kargs)
23
+ Base::PresetView.build_update_input(model, super)
24
+ end
25
+ end
11
26
  end
12
27
  end
13
28
  end
@@ -0,0 +1,19 @@
1
+ module Ecoportal
2
+ module API
3
+ class GraphQL
4
+ module Input
5
+ class WorkflowCommand
6
+ # 20260713: add an item to a checklist field.
7
+ module AddChecklistFieldItem
8
+ SCHEMA_VERSION = '20260713'.freeze
9
+ VALID_KEYS = %i[dataFieldId placeholderId label weight].freeze
10
+
11
+ def self.build(**kwargs)
12
+ kwargs.slice(*VALID_KEYS).compact
13
+ end
14
+ end
15
+ end
16
+ end
17
+ end
18
+ end
19
+ end
@@ -0,0 +1,23 @@
1
+ module Ecoportal
2
+ module API
3
+ class GraphQL
4
+ module Input
5
+ class WorkflowCommand
6
+ # 20260713: smart-fill (AI) configuration extracted from the field-config inputs
7
+ # into its own add/edit/remove command family. `fieldConfigurations` accepts an array
8
+ # of pre-built WorkflowSmartFillFieldConfigurationInput hashes.
9
+ module AddSmartFillConfig
10
+ SCHEMA_VERSION = '20260713'.freeze
11
+ VALID_KEYS = %i[
12
+ dataFieldId triggerType instructions editEnabled textFormat limitLength fieldConfigurations
13
+ ].freeze
14
+
15
+ def self.build(**kwargs)
16
+ kwargs.slice(*VALID_KEYS).compact
17
+ end
18
+ end
19
+ end
20
+ end
21
+ end
22
+ end
23
+ end
@@ -4,8 +4,9 @@ module Ecoportal
4
4
  module Input
5
5
  class WorkflowCommand
6
6
  module AddStage
7
- SCHEMA_VERSION = '20260605'.freeze
8
- VALID_KEYS = %i[placeholderId name ordering].freeze
7
+ SCHEMA_VERSION = '20260713'.freeze
8
+ # 20260713: gained `tags` (create a stage already tagged, rather than adding stage tags after).
9
+ VALID_KEYS = %i[placeholderId name ordering tags].freeze
9
10
 
10
11
  def self.build(**kwargs)
11
12
  kwargs.slice(*VALID_KEYS).compact
@@ -0,0 +1,45 @@
1
+ module Ecoportal
2
+ module API
3
+ class GraphQL
4
+ module Input
5
+ class WorkflowCommand
6
+ # `WorkflowAddViewableFieldInput` — adds a person-schema field to the list of fields
7
+ # shown on a People data field ("viewable fields").
8
+ #
9
+ # ★ This command exists BECAUSE the 20260725 schema drift REMOVED
10
+ # `WorkflowEditFieldConfigurationPeopleInput.addViewableFields: [String!]`. Viewable
11
+ # fields moved from an array on the people field-config to three dedicated commands
12
+ # (add/move/remove), which also bought them ordering (`anchorId` + `anchorPosition`)
13
+ # that the old flat array could not express. Until these were wired, viewable-field
14
+ # management was simply impossible through this gem.
15
+ module AddViewableField
16
+ SCHEMA_VERSION = '20260725'.freeze
17
+ VALID_KEYS = %i[
18
+ dataFieldId schemaFieldId schemaFieldType anchorId anchorPosition
19
+ ].freeze
20
+ # AnchorPositionEnum
21
+ ANCHOR_POSITIONS = %w[BEFORE AFTER].freeze
22
+
23
+ def self.build(data_field_id:, schema_field_id:, **kwargs)
24
+ validate_anchor!(kwargs[:anchorPosition])
25
+
26
+ {
27
+ dataFieldId: data_field_id,
28
+ schemaFieldId: schema_field_id
29
+ }.merge(kwargs.slice(*(VALID_KEYS - %i[dataFieldId schemaFieldId])).compact)
30
+ end
31
+
32
+ def self.validate_anchor!(position)
33
+ return if position.nil? || ANCHOR_POSITIONS.include?(position.to_s)
34
+
35
+ raise ArgumentError,
36
+ "Invalid anchorPosition #{position.inspect}: " \
37
+ "expected one of #{ANCHOR_POSITIONS.join(', ')}"
38
+ end
39
+ private_class_method :validate_anchor!
40
+ end
41
+ end
42
+ end
43
+ end
44
+ end
45
+ end
@@ -0,0 +1,19 @@
1
+ module Ecoportal
2
+ module API
3
+ class GraphQL
4
+ module Input
5
+ class WorkflowCommand
6
+ # 20260713
7
+ module ArchivePublicConfig
8
+ SCHEMA_VERSION = '20260713'.freeze
9
+ VALID_KEYS = %i[archive].freeze # archive: Boolean! (required server-side)
10
+
11
+ def self.build(**kwargs)
12
+ kwargs.slice(*VALID_KEYS).compact
13
+ end
14
+ end
15
+ end
16
+ end
17
+ end
18
+ end
19
+ end
@@ -0,0 +1,19 @@
1
+ module Ecoportal
2
+ module API
3
+ class GraphQL
4
+ module Input
5
+ class WorkflowCommand
6
+ # 20260713: public (anonymous) submission config for a template.
7
+ module CreatePublicConfig
8
+ SCHEMA_VERSION = '20260713'.freeze
9
+ VALID_KEYS = %i[token].freeze
10
+
11
+ def self.build(**kwargs)
12
+ kwargs.slice(*VALID_KEYS).compact
13
+ end
14
+ end
15
+ end
16
+ end
17
+ end
18
+ end
19
+ end
@@ -0,0 +1,19 @@
1
+ module Ecoportal
2
+ module API
3
+ class GraphQL
4
+ module Input
5
+ class WorkflowCommand
6
+ # 20260713
7
+ module EditChecklistFieldItem
8
+ SCHEMA_VERSION = '20260713'.freeze
9
+ VALID_KEYS = %i[dataFieldId itemId label weight].freeze
10
+
11
+ def self.build(**kwargs)
12
+ kwargs.slice(*VALID_KEYS).compact
13
+ end
14
+ end
15
+ end
16
+ end
17
+ end
18
+ end
19
+ end
@@ -4,9 +4,19 @@ module Ecoportal
4
4
  module Input
5
5
  class WorkflowCommand
6
6
  module EditFieldConfiguration
7
- SCHEMA_VERSION = '20260605'.freeze
7
+ SCHEMA_VERSION = '20260713'.freeze
8
8
 
9
- BASE_KEYS = %i[dataFieldId label tooltip description hideView hiddenOnMobile enableActions globalBinding].freeze
9
+ # 20260713: gained addActionIds/removeActionIds (set-diff of field-attached Actions).
10
+ # 20260801: added the three keys the schema has always had but this builder silently
11
+ # dropped — `stageId` (which stage's copy of the field to edit; REQUIRED to
12
+ # disambiguate on a phased page, so its absence made this builder unusable there) and
13
+ # the addPermittedPersonSchemaIds/removePermittedPersonSchemaIds set-diff.
14
+ BASE_KEYS = %i[
15
+ dataFieldId stageId label tooltip description hideView hiddenOnMobile
16
+ enableActions globalBinding
17
+ addActionIds removeActionIds
18
+ addPermittedPersonSchemaIds removePermittedPersonSchemaIds
19
+ ].freeze
10
20
 
11
21
  def self.build(data_field_id:, **kwargs)
12
22
  { dataFieldId: data_field_id }.
@@ -0,0 +1,19 @@
1
+ module Ecoportal
2
+ module API
3
+ class GraphQL
4
+ module Input
5
+ class WorkflowCommand
6
+ # 20260713
7
+ module EditPublicConfig
8
+ SCHEMA_VERSION = '20260713'.freeze
9
+ VALID_KEYS = %i[token].freeze # token: String! (required server-side)
10
+
11
+ def self.build(**kwargs)
12
+ kwargs.slice(*VALID_KEYS).compact
13
+ end
14
+ end
15
+ end
16
+ end
17
+ end
18
+ end
19
+ end
@@ -0,0 +1,21 @@
1
+ module Ecoportal
2
+ module API
3
+ class GraphQL
4
+ module Input
5
+ class WorkflowCommand
6
+ # 20260713
7
+ module EditSmartFillConfig
8
+ SCHEMA_VERSION = '20260713'.freeze
9
+ VALID_KEYS = %i[
10
+ dataFieldId triggerType instructions editEnabled textFormat limitLength fieldConfigurations
11
+ ].freeze
12
+
13
+ def self.build(**kwargs)
14
+ kwargs.slice(*VALID_KEYS).compact
15
+ end
16
+ end
17
+ end
18
+ end
19
+ end
20
+ end
21
+ end
@@ -0,0 +1,19 @@
1
+ module Ecoportal
2
+ module API
3
+ class GraphQL
4
+ module Input
5
+ class WorkflowCommand
6
+ # 20260713
7
+ module EditTemplateAdvancedSettings
8
+ SCHEMA_VERSION = '20260713'.freeze
9
+ VALID_KEYS = %i[addBaseTags removeBaseTags addOtherTags removeOtherTags].freeze
10
+
11
+ def self.build(**kwargs)
12
+ kwargs.slice(*VALID_KEYS).compact
13
+ end
14
+ end
15
+ end
16
+ end
17
+ end
18
+ end
19
+ end
@@ -0,0 +1,27 @@
1
+ module Ecoportal
2
+ module API
3
+ class GraphQL
4
+ module Input
5
+ class WorkflowCommand
6
+ # 20260713: replaces the page-level `editPage` command (template-scoped).
7
+ module EditTemplateBasicSettings
8
+ SCHEMA_VERSION = '20260713'.freeze
9
+ VALID_KEYS = %i[
10
+ name icon themeId timeZone disableDirectPermissions mobileEnabled
11
+ useSectionsOnMobile showStrategyForRestrictedStages
12
+ showAssigneeNamesForRestrictedStages showTaskDueDateForRestrictedStages
13
+ hideActivityStream disableComments hidePageLocationUi enableDashboardImport
14
+ enableActionsOnFields showCreator active counterPrefix counterPostfix
15
+ counterEnabled counter addLocationIds removeLocationIds addFolders removeFolders
16
+ addBaseTags removeBaseTags creatorEnabled creatorEditable creatorFlags
17
+ ].freeze
18
+
19
+ def self.build(**kwargs)
20
+ kwargs.slice(*VALID_KEYS).compact
21
+ end
22
+ end
23
+ end
24
+ end
25
+ end
26
+ end
27
+ end