ecoportal-api-graphql 1.3.11 → 1.3.12

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 (41) hide show
  1. checksums.yaml +4 -4
  2. data/.ai-assistance/code/filter_contract_matrix.md +177 -0
  3. data/.ai-assistance/projects/template-automatic-build-maintenance/INTENT.md +10 -0
  4. data/.ai-assistance/projects/template-automatic-build-maintenance/TODO.md +11 -0
  5. data/.ai-assistance/skills/procedural-memory/SKILL.md +319 -0
  6. data/.ai-assistance/standards-version.json +21 -20
  7. data/CHANGELOG.md +32 -0
  8. data/CLAUDE.md +10 -0
  9. data/docs/self-docs/ARCHITECTURE.md +88 -0
  10. data/docs/self-docs/CHANGES.jsonl +7 -0
  11. data/docs/self-docs/CONVENTIONS.md +74 -0
  12. data/docs/self-docs/INTEGRATIONS.md +63 -0
  13. data/docs/self-docs/OVERVIEW.md +51 -0
  14. data/docs/self-docs/STATUS.md +69 -0
  15. data/docs/self-docs/self-docs-index.json +39 -0
  16. data/docs/worklog.md +0 -23
  17. data/lib/ecoportal/api/common/graphql/model/diffable.rb +54 -54
  18. data/lib/ecoportal/api/graphql/base/action.rb +43 -43
  19. data/lib/ecoportal/api/graphql/base/contractor_entity/member_changes.rb +67 -67
  20. data/lib/ecoportal/api/graphql/base/page/data_field/collection.rb +7 -0
  21. data/lib/ecoportal/api/graphql/base/page/data_field/contractor_entities.rb +28 -28
  22. data/lib/ecoportal/api/graphql/base/page/data_field/file_field.rb +25 -25
  23. data/lib/ecoportal/api/graphql/base/page/data_field/image_gallery.rb +24 -24
  24. data/lib/ecoportal/api/graphql/base/page/section_collection.rb +85 -79
  25. data/lib/ecoportal/api/graphql/base/preset_view.rb +17 -17
  26. data/lib/ecoportal/api/graphql/base/register.rb +18 -18
  27. data/lib/ecoportal/api/graphql/compat/filter_translator.rb +63 -28
  28. data/lib/ecoportal/api/graphql/concerns/page_compat.rb +51 -51
  29. data/lib/ecoportal/api/graphql/concerns.rb +14 -14
  30. data/lib/ecoportal/api/graphql/file_upload/client.rb +181 -181
  31. data/lib/ecoportal/api/graphql/fragment/page.rb +85 -85
  32. data/lib/ecoportal/api/graphql/input/action/update.rb +14 -14
  33. data/lib/ecoportal/api/graphql/input/contractor_entity/update.rb +41 -41
  34. data/lib/ecoportal/api/graphql/input/location_structure/apply_commands.rb +47 -47
  35. data/lib/ecoportal/api/graphql/input/location_structure/draft/add_commands.rb +49 -49
  36. data/lib/ecoportal/api/graphql/input/location_structure/update_command.rb +27 -27
  37. data/lib/ecoportal/api/graphql/input/search_conf.rb +436 -367
  38. data/lib/ecoportal/api/graphql/interface/location_structure/command.rb +30 -30
  39. data/lib/ecoportal/api/graphql/logic/input.rb +26 -26
  40. data/lib/ecoportal/api/graphql_version.rb +1 -1
  41. metadata +10 -1
@@ -1,67 +1,67 @@
1
- module Ecoportal
2
- module API
3
- class GraphQL
4
- module Base
5
- class ContractorEntity
6
- module MemberChanges
7
- def associate(*values, lead: false)
8
- ids = to_person_ids(*values)
9
-
10
- associatedPeopleIds.tap do |associated|
11
- associated.push!(*ids)
12
- next unless lead
13
-
14
- lead!(*ids)
15
- end
16
- end
17
-
18
- def dissassociate(*values)
19
- ids = to_person_ids(*values)
20
-
21
- associatedPeopleIds.tap do |associated|
22
- unlead!(*ids)
23
- associated.delete!(*ids)
24
- end
25
- end
26
-
27
- def lead!(*values)
28
- ids = to_person_ids(*values)
29
-
30
- leadContractorIds.tap do |leads|
31
- associate(*ids)
32
- leads.push!(*ids)
33
- end
34
- end
35
-
36
- def unlead!(*values)
37
- ids = to_person_ids(*values)
38
-
39
- leadContractorIds.tap do |leads|
40
- leads.delete!(*ids)
41
- end
42
- end
43
-
44
- private
45
-
46
- def to_person_ids(*values)
47
- to_person_id(values.flatten)
48
- end
49
-
50
- def to_person_id(value)
51
- case value
52
- when String
53
- value
54
- when Ecoportal::API::V1::Person
55
- value.id
56
- when Hash
57
- to_person_id(['id'])
58
- when Enumarable
59
- value.map {|val| to_person_id(val)}.compact
60
- end
61
- end
62
- end
63
- end
64
- end
65
- end
66
- end
67
- end
1
+ module Ecoportal
2
+ module API
3
+ class GraphQL
4
+ module Base
5
+ class ContractorEntity
6
+ module MemberChanges
7
+ def associate(*values, lead: false)
8
+ ids = to_person_ids(*values)
9
+
10
+ associatedPeopleIds.tap do |associated|
11
+ associated.push!(*ids)
12
+ next unless lead
13
+
14
+ lead!(*ids)
15
+ end
16
+ end
17
+
18
+ def dissassociate(*values)
19
+ ids = to_person_ids(*values)
20
+
21
+ associatedPeopleIds.tap do |associated|
22
+ unlead!(*ids)
23
+ associated.delete!(*ids)
24
+ end
25
+ end
26
+
27
+ def lead!(*values)
28
+ ids = to_person_ids(*values)
29
+
30
+ leadContractorIds.tap do |leads|
31
+ associate(*ids)
32
+ leads.push!(*ids)
33
+ end
34
+ end
35
+
36
+ def unlead!(*values)
37
+ ids = to_person_ids(*values)
38
+
39
+ leadContractorIds.tap do |leads|
40
+ leads.delete!(*ids)
41
+ end
42
+ end
43
+
44
+ private
45
+
46
+ def to_person_ids(*values)
47
+ to_person_id(values.flatten)
48
+ end
49
+
50
+ def to_person_id(value)
51
+ case value
52
+ when String
53
+ value
54
+ when Ecoportal::API::V1::Person
55
+ value.id
56
+ when Hash
57
+ to_person_id(['id'])
58
+ when Enumarable
59
+ value.map {|val| to_person_id(val)}.compact
60
+ end
61
+ end
62
+ end
63
+ end
64
+ end
65
+ end
66
+ end
67
+ end
@@ -37,6 +37,13 @@ module Ecoportal::API::GraphQL::Base::Page
37
37
  pool.find { |f| f.label.to_s.downcase == label.to_s.downcase }
38
38
  end
39
39
 
40
+ # Find a field by its id (v2 compat: components.get_by_id — used by e.g. event-changes /
41
+ # TnG cases that resolve a field by reference_id). Returns the field or nil.
42
+ def get_by_id(id)
43
+ wanted = id.to_s
44
+ @fields.find { |f| f.id.to_s == wanted }
45
+ end
46
+
40
47
  # Raw doc array (v2 compat — scripts iterate secs_doc / flds_doc).
41
48
  def doc
42
49
  @fields.map(&:doc)
@@ -1,28 +1,28 @@
1
- module Ecoportal::API::GraphQL::Base::Page
2
- class DataField
3
- # Contractor entity selector field.
4
- # Stores references to ContractorEntity records.
5
- class ContractorEntities < DataField
6
- passarray :contractors # each: { id:, name: }
7
-
8
- def contractor_entity_ids
9
- Array(contractors).map { |c| c.is_a?(Hash) ? c['id'] : c }.compact
10
- end
11
-
12
- def contractor_entity_ids=(ids)
13
- doc['contractors'] = Array(ids).map { |id_val| { 'id' => id_val } }
14
- end
15
-
16
- # v2 compat alias
17
- def value=(ids)
18
- self.contractor_entity_ids = ids
19
- end
20
-
21
- def as_input
22
- return nil unless dirty?
23
-
24
- { contractorEntities: { id: id, contractorEntityIds: contractor_entity_ids } }
25
- end
26
- end
27
- end
28
- end
1
+ module Ecoportal::API::GraphQL::Base::Page
2
+ class DataField
3
+ # Contractor entity selector field.
4
+ # Stores references to ContractorEntity records.
5
+ class ContractorEntities < DataField
6
+ passarray :contractors # each: { id:, name: }
7
+
8
+ def contractor_entity_ids
9
+ Array(contractors).map { |c| c.is_a?(Hash) ? c['id'] : c }.compact
10
+ end
11
+
12
+ def contractor_entity_ids=(ids)
13
+ doc['contractors'] = Array(ids).map { |id_val| { 'id' => id_val } }
14
+ end
15
+
16
+ # v2 compat alias
17
+ def value=(ids)
18
+ self.contractor_entity_ids = ids
19
+ end
20
+
21
+ def as_input
22
+ return nil unless dirty?
23
+
24
+ { contractorEntities: { id: id, contractorEntityIds: contractor_entity_ids } }
25
+ end
26
+ end
27
+ end
28
+ end
@@ -1,25 +1,25 @@
1
- module Ecoportal::API::GraphQL::Base::Page
2
- class DataField
3
- # File attachment field.
4
- # Writing requires a prior file upload to the REST upload endpoint
5
- # to obtain fileContainerIds — see the file-upload TODO in projects/TODO.md.
6
- # The file_container_ids= setter can be used once IDs are available.
7
- class FileField < DataField
8
- passarray :fileContainers # each: { id:, fileName:, ... }
9
-
10
- def file_container_ids
11
- Array(fileContainers).map { |c| c.is_a?(Hash) ? c['id'] : c }.compact
12
- end
13
-
14
- def file_container_ids=(ids)
15
- doc['fileContainers'] = Array(ids).map { |id_val| { 'id' => id_val } }
16
- end
17
-
18
- def as_input
19
- return nil unless dirty?
20
-
21
- { file: { id: id, fileContainerIds: file_container_ids } }
22
- end
23
- end
24
- end
25
- end
1
+ module Ecoportal::API::GraphQL::Base::Page
2
+ class DataField
3
+ # File attachment field.
4
+ # Writing requires a prior file upload to the REST upload endpoint
5
+ # to obtain fileContainerIds — see the file-upload TODO in projects/TODO.md.
6
+ # The file_container_ids= setter can be used once IDs are available.
7
+ class FileField < DataField
8
+ passarray :fileContainers # each: { id:, fileName:, ... }
9
+
10
+ def file_container_ids
11
+ Array(fileContainers).map { |c| c.is_a?(Hash) ? c['id'] : c }.compact
12
+ end
13
+
14
+ def file_container_ids=(ids)
15
+ doc['fileContainers'] = Array(ids).map { |id_val| { 'id' => id_val } }
16
+ end
17
+
18
+ def as_input
19
+ return nil unless dirty?
20
+
21
+ { file: { id: id, fileContainerIds: file_container_ids } }
22
+ end
23
+ end
24
+ end
25
+ end
@@ -1,24 +1,24 @@
1
- module Ecoportal::API::GraphQL::Base::Page
2
- class DataField
3
- # Image gallery field.
4
- # Writing requires a prior file upload to the REST upload endpoint
5
- # to obtain fileContainerIds — see the file-upload TODO in projects/TODO.md.
6
- class ImageGallery < DataField
7
- passarray :fileContainers # each: { id:, fileName:, url:, ... }
8
-
9
- def file_container_ids
10
- Array(fileContainers).map { |c| c.is_a?(Hash) ? c['id'] : c }.compact
11
- end
12
-
13
- def file_container_ids=(ids)
14
- doc['fileContainers'] = Array(ids).map { |id_val| { 'id' => id_val } }
15
- end
16
-
17
- def as_input
18
- return nil unless dirty?
19
-
20
- { imageGallery: { id: id, fileContainerIds: file_container_ids } }
21
- end
22
- end
23
- end
24
- end
1
+ module Ecoportal::API::GraphQL::Base::Page
2
+ class DataField
3
+ # Image gallery field.
4
+ # Writing requires a prior file upload to the REST upload endpoint
5
+ # to obtain fileContainerIds — see the file-upload TODO in projects/TODO.md.
6
+ class ImageGallery < DataField
7
+ passarray :fileContainers # each: { id:, fileName:, url:, ... }
8
+
9
+ def file_container_ids
10
+ Array(fileContainers).map { |c| c.is_a?(Hash) ? c['id'] : c }.compact
11
+ end
12
+
13
+ def file_container_ids=(ids)
14
+ doc['fileContainers'] = Array(ids).map { |id_val| { 'id' => id_val } }
15
+ end
16
+
17
+ def as_input
18
+ return nil unless dirty?
19
+
20
+ { imageGallery: { id: id, fileContainerIds: file_container_ids } }
21
+ end
22
+ end
23
+ end
24
+ end
@@ -1,79 +1,85 @@
1
- module Ecoportal
2
- module API
3
- class GraphQL
4
- module Base
5
- module Page
6
- # Wraps an array of raw section docs as typed Section objects.
7
- # Provides v2-compatible access patterns:
8
- # sections.get_by_type(:content_section)
9
- # sections.doc — raw doc array
10
- # sections.ordered — sections in response order
11
- # sections.each { |s| s.components ... }
12
- class SectionCollection
13
- include Enumerable
14
-
15
- def initialize(sections_array)
16
- @sections = Array(sections_array).map { |s| Section.new(s) }
17
- end
18
-
19
- def self.from_doc(raw_array)
20
- new(Array(raw_array))
21
- end
22
-
23
- # Filter by section type. Accepts symbol (:content_section / :split_section)
24
- # or string ('ContentSection' / 'SplitSection'). Case-insensitive, underscore-tolerant.
25
- def get_by_type(type_key)
26
- target = normalise_type(type_key)
27
- @sections.select { |s| normalise_type(s.type) == target }
28
- end
29
-
30
- # Find section by heading (case-insensitive).
31
- def get_by_heading(heading)
32
- @sections.find { |s| s.heading.to_s.downcase == heading.to_s.downcase }
33
- end
34
-
35
- # Raw doc array v2 compat (scripts iterate sections.doc).
36
- def doc
37
- @sections.map(&:doc)
38
- end
39
-
40
- # Sections in response order (already ordered from server).
41
- def ordered
42
- @sections
43
- end
44
-
45
- # All data fields across every section in this collection (memoized).
46
- def components
47
- @components ||= begin
48
- all_docs = @sections.flat_map do |s|
49
- (s.doc['dataFields'] || []) +
50
- (s.doc['leftDataFields'] || []) +
51
- (s.doc['rightDataFields'] || [])
52
- end
53
- DataField::Collection.from_doc(all_docs)
54
- end
55
- end
56
-
57
- def each(&block)
58
- @sections.each(&block)
59
- end
60
-
61
- def empty?
62
- @sections.empty?
63
- end
64
-
65
- def length
66
- @sections.length
67
- end
68
-
69
- private
70
-
71
- def normalise_type(type_key)
72
- type_key.to_s.downcase.delete('_') if type_key
73
- end
74
- end
75
- end
76
- end
77
- end
78
- end
79
- end
1
+ module Ecoportal
2
+ module API
3
+ class GraphQL
4
+ module Base
5
+ module Page
6
+ # Wraps an array of raw section docs as typed Section objects.
7
+ # Provides v2-compatible access patterns:
8
+ # sections.get_by_type(:content_section)
9
+ # sections.doc — raw doc array
10
+ # sections.ordered — sections in response order
11
+ # sections.each { |s| s.components ... }
12
+ class SectionCollection
13
+ include Enumerable
14
+
15
+ def initialize(sections_array)
16
+ @sections = Array(sections_array).map { |s| Section.new(s) }
17
+ end
18
+
19
+ def self.from_doc(raw_array)
20
+ new(Array(raw_array))
21
+ end
22
+
23
+ # Filter by section type. Accepts symbol (:content_section / :split_section)
24
+ # or string ('ContentSection' / 'SplitSection'). Case-insensitive, underscore-tolerant.
25
+ def get_by_type(type_key)
26
+ target = normalise_type(type_key)
27
+ @sections.select { |s| normalise_type(s.type) == target }
28
+ end
29
+
30
+ # Find section by heading (case-insensitive).
31
+ def get_by_heading(heading)
32
+ @sections.find { |s| s.heading.to_s.downcase == heading.to_s.downcase }
33
+ end
34
+
35
+ # Find a section by its id (v2 compat: sections.get_by_id). Returns the section or nil.
36
+ def get_by_id(id)
37
+ wanted = id.to_s
38
+ @sections.find { |s| s.id.to_s == wanted }
39
+ end
40
+
41
+ # Raw doc array — v2 compat (scripts iterate sections.doc).
42
+ def doc
43
+ @sections.map(&:doc)
44
+ end
45
+
46
+ # Sections in response order (already ordered from server).
47
+ def ordered
48
+ @sections
49
+ end
50
+
51
+ # All data fields across every section in this collection (memoized).
52
+ def components
53
+ @components ||= begin
54
+ all_docs = @sections.flat_map do |s|
55
+ (s.doc['dataFields'] || []) +
56
+ (s.doc['leftDataFields'] || []) +
57
+ (s.doc['rightDataFields'] || [])
58
+ end
59
+ DataField::Collection.from_doc(all_docs)
60
+ end
61
+ end
62
+
63
+ def each(&block)
64
+ @sections.each(&block)
65
+ end
66
+
67
+ def empty?
68
+ @sections.empty?
69
+ end
70
+
71
+ def length
72
+ @sections.length
73
+ end
74
+
75
+ private
76
+
77
+ def normalise_type(type_key)
78
+ type_key.to_s.downcase.delete('_') if type_key
79
+ end
80
+ end
81
+ end
82
+ end
83
+ end
84
+ end
85
+ end
@@ -1,17 +1,17 @@
1
- module Ecoportal
2
- module API
3
- class GraphQL
4
- module Base
5
- # A register preset view — saved column/sort/filter configuration for previewPages.
6
- # Scripts use the id as `presetViewId` in register.previewPages queries.
7
- class PresetView < Logic::BaseModel
8
- passkey :id
9
- passthrough :name, :registerId
10
- passboolean :global
11
- passarray :fieldConfigurations
12
- passthrough :sorter # { key:, direction:, missing: }
13
- end
14
- end
15
- end
16
- end
17
- end
1
+ module Ecoportal
2
+ module API
3
+ class GraphQL
4
+ module Base
5
+ # A register preset view — saved column/sort/filter configuration for previewPages.
6
+ # Scripts use the id as `presetViewId` in register.previewPages queries.
7
+ class PresetView < Logic::BaseModel
8
+ passkey :id
9
+ passthrough :name, :registerId
10
+ passboolean :global
11
+ passarray :fieldConfigurations
12
+ passthrough :sorter # { key:, direction:, missing: }
13
+ end
14
+ end
15
+ end
16
+ end
17
+ end
@@ -1,18 +1,18 @@
1
- module Ecoportal
2
- module API
3
- class GraphQL
4
- module Base
5
- class Register < Logic::BaseModel
6
- passkey :id
7
- passthrough :name, :iconName, :moduleType, :registerStatus
8
- passthrough :descriptionText, :descriptionImageUrl
9
- passboolean :shown, :creatable, :attachable, :permissioned
10
- passboolean :contentShareable, :enableEmailOut, :isMobile
11
- passboolean :restrictTemplatesAmount
12
- passthrough :restrictedAmountOfTemplates
13
- passarray :filterTags
14
- end
15
- end
16
- end
17
- end
18
- end
1
+ module Ecoportal
2
+ module API
3
+ class GraphQL
4
+ module Base
5
+ class Register < Logic::BaseModel
6
+ passkey :id
7
+ passthrough :name, :iconName, :moduleType, :registerStatus
8
+ passthrough :descriptionText, :descriptionImageUrl
9
+ passboolean :shown, :creatable, :attachable, :permissioned
10
+ passboolean :contentShareable, :enableEmailOut, :isMobile
11
+ passboolean :restrictTemplatesAmount
12
+ passthrough :restrictedAmountOfTemplates
13
+ passarray :filterTags
14
+ end
15
+ end
16
+ end
17
+ end
18
+ end