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.
- checksums.yaml +4 -4
- data/CHANGELOG.md +384 -6
- data/lib/ecoportal/api/common/graphql/model/diffable/leaf_diff_service.rb +97 -0
- data/lib/ecoportal/api/common/graphql/model/diffable.rb +1 -0
- data/lib/ecoportal/api/graphql/base/action.rb +1 -1
- data/lib/ecoportal/api/graphql/base/action_event.rb +23 -0
- data/lib/ecoportal/api/graphql/base/action_event_page.rb +16 -0
- data/lib/ecoportal/api/graphql/base/activity.rb +38 -0
- data/lib/ecoportal/api/graphql/base/activity_log.rb +38 -0
- data/lib/ecoportal/api/graphql/base/ai_summary_version.rb +12 -7
- data/lib/ecoportal/api/graphql/base/auth_log.rb +24 -0
- data/lib/ecoportal/api/graphql/base/authorization_result.rb +20 -0
- data/lib/ecoportal/api/graphql/base/contractor_entity/member_changes.rb +17 -5
- data/lib/ecoportal/api/graphql/base/file_container.rb +12 -4
- data/lib/ecoportal/api/graphql/base/location_classification_type.rb +2 -0
- data/lib/ecoportal/api/graphql/base/location_structure.rb +3 -0
- data/lib/ecoportal/api/graphql/base/minimal_dashboard.rb +25 -0
- data/lib/ecoportal/api/graphql/base/organization.rb +2 -0
- data/lib/ecoportal/api/graphql/base/page/data_field/contractor_entities.rb +26 -3
- data/lib/ecoportal/api/graphql/base/page/data_field/file_field.rb +47 -8
- data/lib/ecoportal/api/graphql/base/page/data_field/image_gallery.rb +5 -2
- data/lib/ecoportal/api/graphql/base/page/data_field/people.rb +50 -12
- data/lib/ecoportal/api/graphql/base/page/data_field.rb +12 -18
- data/lib/ecoportal/api/graphql/base/permissions.rb +15 -0
- data/lib/ecoportal/api/graphql/base/person_member_changelog.rb +23 -0
- data/lib/ecoportal/api/graphql/base/preset_view.rb +136 -1
- data/lib/ecoportal/api/graphql/base/register.rb +5 -0
- data/lib/ecoportal/api/graphql/base.rb +9 -0
- data/lib/ecoportal/api/graphql/builder/contractor_entity.rb +10 -0
- data/lib/ecoportal/api/graphql/builder/page.rb +0 -16
- data/lib/ecoportal/api/graphql/builder/template.rb +18 -0
- data/lib/ecoportal/api/graphql/compat/pages.rb +7 -2
- data/lib/ecoportal/api/graphql/compat/response.rb +14 -0
- data/lib/ecoportal/api/graphql/concerns/threadable.rb +58 -0
- data/lib/ecoportal/api/graphql/concerns.rb +1 -0
- data/lib/ecoportal/api/graphql/connection/action.rb +1 -1
- data/lib/ecoportal/api/graphql/connection/action_category.rb +1 -1
- data/lib/ecoportal/api/graphql/connection/activity.rb +11 -0
- data/lib/ecoportal/api/graphql/connection/activity_log.rb +11 -0
- data/lib/ecoportal/api/graphql/connection/auth_log.rb +11 -0
- data/lib/ecoportal/api/graphql/connection/contractor_entity.rb +1 -1
- data/lib/ecoportal/api/graphql/connection/minimal_dashboard.rb +11 -0
- data/lib/ecoportal/api/graphql/connection/page.rb +1 -1
- data/lib/ecoportal/api/graphql/connection/pages_workflow_command.rb +1 -1
- data/lib/ecoportal/api/graphql/connection/person_member.rb +1 -1
- data/lib/ecoportal/api/graphql/connection/person_member_changelog.rb +11 -0
- data/lib/ecoportal/api/graphql/connection/preview_page.rb +1 -1
- data/lib/ecoportal/api/graphql/connection.rb +5 -0
- data/lib/ecoportal/api/graphql/diff/pairing/signals.rb +21 -1
- data/lib/ecoportal/api/graphql/file_upload/client.rb +199 -140
- data/lib/ecoportal/api/graphql/fragment/activity.rb +84 -0
- data/lib/ecoportal/api/graphql/fragment/activity_log.rb +75 -0
- data/lib/ecoportal/api/graphql/fragment/auth_log.rb +29 -0
- data/lib/ecoportal/api/graphql/fragment/authorization_result.rb +14 -0
- data/lib/ecoportal/api/graphql/fragment/location_node.rb +1 -0
- data/lib/ecoportal/api/graphql/fragment/minimal_dashboard.rb +31 -0
- data/lib/ecoportal/api/graphql/fragment/pages/common_page_union.rb +21 -0
- data/lib/ecoportal/api/graphql/fragment/permissions.rb +98 -0
- data/lib/ecoportal/api/graphql/fragment/person_member_changelog.rb +33 -0
- data/lib/ecoportal/api/graphql/fragment.rb +7 -0
- data/lib/ecoportal/api/graphql/input/action/update.rb +12 -0
- data/lib/ecoportal/api/graphql/input/contractor_entity/manager_settings.rb +20 -0
- data/lib/ecoportal/api/graphql/input/contractor_entity/update.rb +6 -27
- data/lib/ecoportal/api/graphql/input/contractor_entity.rb +1 -0
- data/lib/ecoportal/api/graphql/input/date_range.rb +16 -0
- data/lib/ecoportal/api/graphql/input/location_structure/apply_commands.rb +2 -2
- data/lib/ecoportal/api/graphql/input/location_structure/draft/add_commands.rb +2 -2
- data/lib/ecoportal/api/graphql/input/location_structure/update_command.rb +6 -2
- data/lib/ecoportal/api/graphql/input/preset_view/update.rb +16 -1
- data/lib/ecoportal/api/graphql/input/workflow_command/add_checklist_field_item.rb +19 -0
- data/lib/ecoportal/api/graphql/input/workflow_command/add_smart_fill_config.rb +23 -0
- data/lib/ecoportal/api/graphql/input/workflow_command/add_stage.rb +3 -2
- data/lib/ecoportal/api/graphql/input/workflow_command/add_viewable_field.rb +45 -0
- data/lib/ecoportal/api/graphql/input/workflow_command/archive_public_config.rb +19 -0
- data/lib/ecoportal/api/graphql/input/workflow_command/create_public_config.rb +19 -0
- data/lib/ecoportal/api/graphql/input/workflow_command/edit_checklist_field_item.rb +19 -0
- data/lib/ecoportal/api/graphql/input/workflow_command/edit_field_configuration.rb +12 -2
- data/lib/ecoportal/api/graphql/input/workflow_command/edit_public_config.rb +19 -0
- data/lib/ecoportal/api/graphql/input/workflow_command/edit_smart_fill_config.rb +21 -0
- data/lib/ecoportal/api/graphql/input/workflow_command/edit_template_advanced_settings.rb +19 -0
- data/lib/ecoportal/api/graphql/input/workflow_command/edit_template_basic_settings.rb +27 -0
- data/lib/ecoportal/api/graphql/input/workflow_command/edit_template_container_uid.rb +45 -0
- data/lib/ecoportal/api/graphql/input/workflow_command/{edit_page_creator_permissions.rb → edit_template_creator_permissions.rb} +3 -2
- data/lib/ecoportal/api/graphql/input/workflow_command/edit_template_descriptions.rb +19 -0
- data/lib/ecoportal/api/graphql/input/workflow_command/field_config/action_list.rb +31 -0
- data/lib/ecoportal/api/graphql/input/workflow_command/field_config/cross_reference.rb +3 -1
- data/lib/ecoportal/api/graphql/input/workflow_command/field_config/date.rb +15 -2
- data/lib/ecoportal/api/graphql/input/workflow_command/field_config/file.rb +21 -0
- data/lib/ecoportal/api/graphql/input/workflow_command/field_config/image_gallery.rb +3 -2
- data/lib/ecoportal/api/graphql/input/workflow_command/field_config/people.rb +27 -3
- data/lib/ecoportal/api/graphql/input/workflow_command/field_config/plain_text.rb +3 -2
- data/lib/ecoportal/api/graphql/input/workflow_command/field_config/rich_text.rb +3 -2
- data/lib/ecoportal/api/graphql/input/workflow_command/field_config/select.rb +3 -2
- data/lib/ecoportal/api/graphql/input/workflow_command/move_field.rb +3 -2
- data/lib/ecoportal/api/graphql/input/workflow_command/move_viewable_field.rb +33 -0
- data/lib/ecoportal/api/graphql/input/workflow_command/remove_checklist_field_item.rb +19 -0
- data/lib/ecoportal/api/graphql/input/workflow_command/remove_smart_fill_config.rb +19 -0
- data/lib/ecoportal/api/graphql/input/workflow_command/remove_viewable_field.rb +21 -0
- data/lib/ecoportal/api/graphql/input/workflow_command/reorder_forces.rb +3 -2
- data/lib/ecoportal/api/graphql/input/workflow_command/reorder_section.rb +3 -2
- data/lib/ecoportal/api/graphql/input/workflow_command.rb +43 -5
- data/lib/ecoportal/api/graphql/input.rb +1 -0
- data/lib/ecoportal/api/graphql/interface/base_page.rb +36 -3
- data/lib/ecoportal/api/graphql/interface/location_structure/command.rb +2 -1
- data/lib/ecoportal/api/graphql/logic/connection.rb +17 -0
- data/lib/ecoportal/api/graphql/logic/input.rb +127 -0
- data/lib/ecoportal/api/graphql/model/action_event.rb +14 -0
- data/lib/ecoportal/api/graphql/model/action_event_page.rb +10 -0
- data/lib/ecoportal/api/graphql/model/activity.rb +14 -0
- data/lib/ecoportal/api/graphql/model/activity_log.rb +31 -0
- data/lib/ecoportal/api/graphql/model/auth_log.rb +11 -0
- data/lib/ecoportal/api/graphql/model/authorization_result.rb +12 -0
- data/lib/ecoportal/api/graphql/model/minimal_dashboard.rb +14 -0
- data/lib/ecoportal/api/graphql/model/organization.rb +27 -0
- data/lib/ecoportal/api/graphql/model/permissions.rb +179 -0
- data/lib/ecoportal/api/graphql/model/person_member.rb +7 -0
- data/lib/ecoportal/api/graphql/model/person_member_changelog.rb +15 -0
- data/lib/ecoportal/api/graphql/model.rb +9 -0
- data/lib/ecoportal/api/graphql/mutation/ai_summary/generate.rb +20 -10
- data/lib/ecoportal/api/graphql/mutation/ai_summary/submit_feedback.rb +25 -10
- data/lib/ecoportal/api/graphql/mutation/contractor_entity/update_manager_settings.rb +37 -0
- data/lib/ecoportal/api/graphql/mutation/contractor_entity.rb +1 -0
- data/lib/ecoportal/api/graphql/mutation/file_container/upload.rb +78 -0
- data/lib/ecoportal/api/graphql/mutation/file_container.rb +15 -0
- data/lib/ecoportal/api/graphql/mutation/template/update_related_page.rb +79 -0
- data/lib/ecoportal/api/graphql/mutation/template.rb +1 -0
- data/lib/ecoportal/api/graphql/mutation.rb +1 -1
- data/lib/ecoportal/api/graphql/payload/contractor_entity/manager_settings.rb +20 -0
- data/lib/ecoportal/api/graphql/payload/contractor_entity.rb +1 -0
- data/lib/ecoportal/api/graphql/payload/template/update_related_page.rb +15 -0
- data/lib/ecoportal/api/graphql/payload/template.rb +1 -0
- data/lib/ecoportal/api/graphql/payload/upload.rb +12 -0
- data/lib/ecoportal/api/graphql/payload.rb +1 -0
- data/lib/ecoportal/api/graphql/query/activity_logs.rb +78 -0
- data/lib/ecoportal/api/graphql/query/auth_logs.rb +51 -0
- data/lib/ecoportal/api/graphql/query/dashboard_search.rb +57 -0
- data/lib/ecoportal/api/graphql/query/location_structure.rb +2 -0
- data/lib/ecoportal/api/graphql/query/location_structures.rb +2 -0
- data/lib/ecoportal/api/graphql/query/page.rb +6 -1
- data/lib/ecoportal/api/graphql/query/page_activities.rb +56 -0
- data/lib/ecoportal/api/graphql/query/permissions.rb +35 -0
- data/lib/ecoportal/api/graphql/query/person_member_changelogs.rb +53 -0
- data/lib/ecoportal/api/graphql/query.rb +6 -0
- data/lib/ecoportal/api/graphql_version.rb +1 -1
- metadata +73 -12
- data/lib/ecoportal/api/graphql/input/workflow_command/edit_page.rb +0 -28
- data/lib/ecoportal/api/graphql/mutation/smart_fill/generate.rb +0 -36
- data/lib/ecoportal/api/graphql/mutation/smart_fill/submit_feedback.rb +0 -40
- data/lib/ecoportal/api/graphql/mutation/smart_fill.rb +0 -13
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
module Ecoportal
|
|
2
|
+
module API
|
|
3
|
+
class GraphQL
|
|
4
|
+
module Input
|
|
5
|
+
class WorkflowCommand
|
|
6
|
+
# `WorkflowEditTemplateContainerUidInput { templateContainerUid: String! }`.
|
|
7
|
+
#
|
|
8
|
+
# Sets the template's CROSS-VERSION identity key. Semantics (verified against the
|
|
9
|
+
# backend on 2026-07-31 — see `.ai-assistance/code/ecoPortal_architecture/02_data_model.md`):
|
|
10
|
+
#
|
|
11
|
+
# - Format `/\A[a-zA-Z0-9\-_.]{3,20}\z/` — org-scoped, human-authored.
|
|
12
|
+
# - Many versions of a template may share one uid, but only ONE may be published
|
|
13
|
+
# (`active: true`, unarchived) per organization at a time. Publishing another with
|
|
14
|
+
# the same uid UNPUBLISHES the incumbent (a swap, not an error), which is what stops
|
|
15
|
+
# restored UAT backups from colliding with the live PROD template.
|
|
16
|
+
# - Rejected with `:template_container_uid, :taken` when the swap is not permitted.
|
|
17
|
+
# - Requires `Pages::TemplatePolicy#change_template_container_uid?`
|
|
18
|
+
# (`required_level: :implement`).
|
|
19
|
+
#
|
|
20
|
+
# The value is REQUIRED and non-null in the schema, so nil is rejected here rather
|
|
21
|
+
# than silently dropped — `.compact` (as used by the sibling builders) would emit an
|
|
22
|
+
# empty command that the server rejects with a less obvious message.
|
|
23
|
+
module EditTemplateContainerUid
|
|
24
|
+
SCHEMA_VERSION = '20260731'.freeze
|
|
25
|
+
VALID_KEYS = %i[templateContainerUid].freeze
|
|
26
|
+
UID_FORMAT = /\A[a-zA-Z0-9\-_.]{3,20}\z/
|
|
27
|
+
|
|
28
|
+
def self.build(**kwargs)
|
|
29
|
+
uid = kwargs[:templateContainerUid]
|
|
30
|
+
raise ArgumentError, 'templateContainerUid is required (String!)' if uid.nil?
|
|
31
|
+
|
|
32
|
+
unless UID_FORMAT.match?(uid.to_s)
|
|
33
|
+
raise ArgumentError,
|
|
34
|
+
"Invalid templateContainerUid #{uid.inspect}: " \
|
|
35
|
+
'use 3-20 characters (letters, numbers, -, _, . only)'
|
|
36
|
+
end
|
|
37
|
+
|
|
38
|
+
{ templateContainerUid: uid.to_s }
|
|
39
|
+
end
|
|
40
|
+
end
|
|
41
|
+
end
|
|
42
|
+
end
|
|
43
|
+
end
|
|
44
|
+
end
|
|
45
|
+
end
|
|
@@ -3,8 +3,9 @@ module Ecoportal
|
|
|
3
3
|
class GraphQL
|
|
4
4
|
module Input
|
|
5
5
|
class WorkflowCommand
|
|
6
|
-
|
|
7
|
-
|
|
6
|
+
# 20260713: replaces the page-level `editPageCreatorPermissions` command (template-scoped).
|
|
7
|
+
module EditTemplateCreatorPermissions
|
|
8
|
+
SCHEMA_VERSION = '20260713'.freeze
|
|
8
9
|
VALID_KEYS = %i[creatorEnabled creatorEditable creatorFlags].freeze
|
|
9
10
|
|
|
10
11
|
def self.build(**kwargs)
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
module Ecoportal
|
|
2
|
+
module API
|
|
3
|
+
class GraphQL
|
|
4
|
+
module Input
|
|
5
|
+
class WorkflowCommand
|
|
6
|
+
# 20260713
|
|
7
|
+
module EditTemplateDescriptions
|
|
8
|
+
SCHEMA_VERSION = '20260713'.freeze
|
|
9
|
+
VALID_KEYS = %i[description aiDescription templateType].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,31 @@
|
|
|
1
|
+
module Ecoportal
|
|
2
|
+
module API
|
|
3
|
+
class GraphQL
|
|
4
|
+
module Input
|
|
5
|
+
class WorkflowCommand
|
|
6
|
+
module EditFieldConfiguration
|
|
7
|
+
# `WorkflowEditFieldConfigurationActionListInput` — the 14th (and last unwired)
|
|
8
|
+
# member of `WorkflowEditFieldConfigurationByTypeInput`. Added to the schema in the
|
|
9
|
+
# 20260725 drift and never picked up, which left ActionsList the one field type whose
|
|
10
|
+
# configuration could not be edited through this gem.
|
|
11
|
+
#
|
|
12
|
+
# NOTE the naming asymmetry, which is the schema's, not ours: the byType KEY is
|
|
13
|
+
# `actionList` (singular) while the field TYPE is `ActionsList` (plural) — hence
|
|
14
|
+
# `Base::Page::DataField::TYPE_MAP` maps `'ActionsList'`. Keep this module named after
|
|
15
|
+
# the byType key so the registry lookup stays mechanical.
|
|
16
|
+
module ActionList
|
|
17
|
+
SCHEMA_VERSION = '20260725'.freeze
|
|
18
|
+
VALID_KEYS = %i[requiredCompleted].freeze
|
|
19
|
+
# ActionsListRequiredCompletedEnum (verified against the live schema, 20260731)
|
|
20
|
+
REQUIRED_COMPLETED = %w[NONE SOME ALL].freeze
|
|
21
|
+
|
|
22
|
+
def self.build(**kwargs)
|
|
23
|
+
{ actionList: kwargs.slice(*VALID_KEYS).compact }
|
|
24
|
+
end
|
|
25
|
+
end
|
|
26
|
+
end
|
|
27
|
+
end
|
|
28
|
+
end
|
|
29
|
+
end
|
|
30
|
+
end
|
|
31
|
+
end
|
|
@@ -5,10 +5,12 @@ module Ecoportal
|
|
|
5
5
|
class WorkflowCommand
|
|
6
6
|
module EditFieldConfiguration
|
|
7
7
|
module CrossReference
|
|
8
|
-
SCHEMA_VERSION = '
|
|
8
|
+
SCHEMA_VERSION = '20260713'.freeze
|
|
9
|
+
# 20260713: gained addReferenceIds/removeReferenceIds (set-diff of attached references).
|
|
9
10
|
VALID_KEYS = %i[
|
|
10
11
|
displayFields displayFieldsInLookup hideCreate hideAttach hideMetadata
|
|
11
12
|
registerId attachSourcePage hideDashboards singleSelectMode
|
|
13
|
+
addReferenceIds removeReferenceIds
|
|
12
14
|
].freeze
|
|
13
15
|
|
|
14
16
|
def self.build(**kwargs)
|
|
@@ -5,8 +5,21 @@ module Ecoportal
|
|
|
5
5
|
class WorkflowCommand
|
|
6
6
|
module EditFieldConfiguration
|
|
7
7
|
module Date
|
|
8
|
-
SCHEMA_VERSION = '
|
|
9
|
-
|
|
8
|
+
SCHEMA_VERSION = '20260725'.freeze
|
|
9
|
+
# 20260713: smartFillConfiguration moved out to dedicated add/edit/removeSmartFillConfig commands.
|
|
10
|
+
# 20260725: gained the date-EVENT and RENEWAL keys below (calendar events + recurring
|
|
11
|
+
# expiry on a date field). Six keys that had never been reachable from this gem —
|
|
12
|
+
# renewals are how expiry-driven registers (certifications, inductions, permits)
|
|
13
|
+
# are configured, so this was a real functional hole, not a cosmetic one.
|
|
14
|
+
VALID_KEYS = %i[
|
|
15
|
+
showTime pastOnly todayButton
|
|
16
|
+
createEvent remindMeIn
|
|
17
|
+
renews renewsEvery renewsUnit renewsUntil
|
|
18
|
+
].freeze
|
|
19
|
+
# PagesDataFieldsDatesRenewsUnitEnum
|
|
20
|
+
RENEWS_UNITS = %w[DAY WEEK MONTH YEAR].freeze
|
|
21
|
+
# DateEventRemindOption
|
|
22
|
+
REMIND_OPTIONS = %w[NEVER ONE_DAY THREE_DAYS ONE_WEEK TWO_WEEKS ONE_MONTH].freeze
|
|
10
23
|
|
|
11
24
|
def self.build(**kwargs)
|
|
12
25
|
{ date: kwargs.slice(*VALID_KEYS).compact }
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
module Ecoportal
|
|
2
|
+
module API
|
|
3
|
+
class GraphQL
|
|
4
|
+
module Input
|
|
5
|
+
class WorkflowCommand
|
|
6
|
+
module EditFieldConfiguration
|
|
7
|
+
# 20260713: `file` by-type field configuration (set-diff of file containers/items).
|
|
8
|
+
module File
|
|
9
|
+
SCHEMA_VERSION = '20260713'.freeze
|
|
10
|
+
VALID_KEYS = %i[addFileContainerIds removeItemIds].freeze
|
|
11
|
+
|
|
12
|
+
def self.build(**kwargs)
|
|
13
|
+
{ file: kwargs.slice(*VALID_KEYS).compact }
|
|
14
|
+
end
|
|
15
|
+
end
|
|
16
|
+
end
|
|
17
|
+
end
|
|
18
|
+
end
|
|
19
|
+
end
|
|
20
|
+
end
|
|
21
|
+
end
|
|
@@ -5,8 +5,9 @@ module Ecoportal
|
|
|
5
5
|
class WorkflowCommand
|
|
6
6
|
module EditFieldConfiguration
|
|
7
7
|
module ImageGallery
|
|
8
|
-
SCHEMA_VERSION = '
|
|
9
|
-
|
|
8
|
+
SCHEMA_VERSION = '20260713'.freeze
|
|
9
|
+
# 20260713: gained addImageSourceIds/removeImageIds (set-diff of gallery images).
|
|
10
|
+
VALID_KEYS = %i[layout stretch noPopup hideOptions addImageSourceIds removeImageIds].freeze
|
|
10
11
|
|
|
11
12
|
def self.build(**kwargs)
|
|
12
13
|
{ imageGallery: kwargs.slice(*VALID_KEYS).compact }
|
|
@@ -5,15 +5,39 @@ module Ecoportal
|
|
|
5
5
|
class WorkflowCommand
|
|
6
6
|
module EditFieldConfiguration
|
|
7
7
|
module People
|
|
8
|
-
SCHEMA_VERSION = '
|
|
8
|
+
SCHEMA_VERSION = '20260725'.freeze
|
|
9
|
+
# 20260725: `addViewableFields`/`removeViewableFields` were REMOVED from
|
|
10
|
+
# WorkflowEditFieldConfigurationPeopleInput — they lived on here as dead keys the
|
|
11
|
+
# server rejects. Viewable fields are now three dedicated commands
|
|
12
|
+
# (add/move/removeViewableField), which also added ordering the flat arrays could
|
|
13
|
+
# not express. The same drift added the six attached-people-permission /
|
|
14
|
+
# allowed-user-group keys below, which had never been reachable from this gem.
|
|
9
15
|
VALID_KEYS = %i[
|
|
10
16
|
personSchemaId singular requiresNumber attachMode isMeButton
|
|
11
17
|
autoSelectMode autoSelectSupervisorFieldRef autoSelectDefaultLocations
|
|
12
|
-
|
|
18
|
+
addAllowedUserGroupIds removeAllowedUserGroupIds
|
|
19
|
+
attachedPeoplePermissionsEnabled attachedPeoplePermissionsEditable
|
|
20
|
+
attachedPeoplePermissionsFlags applyAttachedPeoplePermissionsTo
|
|
21
|
+
].freeze
|
|
22
|
+
# WorkflowAutoSelectModeEnum — `autoSelectMode` was retyped String -> enum in the
|
|
23
|
+
# same drift. Values pass through as strings (valid for enum variables).
|
|
24
|
+
AUTO_SELECT_MODES = %w[NONE CREATOR CREATOR_SUPERVISOR PEOPLE_SUPERVISOR].freeze
|
|
25
|
+
# WorkflowApplyAttachedPeoplePermissionsToEnum
|
|
26
|
+
APPLY_PERMISSIONS_TO = %w[PAGE_ONLY PAGE ALL_STAGES CURRENT_STAGE].freeze
|
|
27
|
+
# Nested WorkflowEditFieldConfigurationAttachedPeoplePermissionsFlagsInput keys.
|
|
28
|
+
PERMISSION_FLAGS = %i[
|
|
29
|
+
canRestructure canConfigure canPermission canCreateActions
|
|
30
|
+
canAdministrateActions subscribed subscribedToTasks
|
|
13
31
|
].freeze
|
|
14
32
|
|
|
15
33
|
def self.build(**kwargs)
|
|
16
|
-
|
|
34
|
+
out = kwargs.slice(*VALID_KEYS).compact
|
|
35
|
+
# Filter the nested flags hash to the keys the schema actually declares, so a
|
|
36
|
+
# stray key can't sink the whole command server-side.
|
|
37
|
+
if (flags = out[:attachedPeoplePermissionsFlags]).is_a?(Hash)
|
|
38
|
+
out[:attachedPeoplePermissionsFlags] = flags.slice(*PERMISSION_FLAGS).compact
|
|
39
|
+
end
|
|
40
|
+
{ people: out }
|
|
17
41
|
end
|
|
18
42
|
end
|
|
19
43
|
end
|
|
@@ -5,8 +5,9 @@ module Ecoportal
|
|
|
5
5
|
class WorkflowCommand
|
|
6
6
|
module EditFieldConfiguration
|
|
7
7
|
module PlainText
|
|
8
|
-
SCHEMA_VERSION = '
|
|
9
|
-
|
|
8
|
+
SCHEMA_VERSION = '20260713'.freeze
|
|
9
|
+
# 20260713: smartFillConfiguration moved out to dedicated add/edit/removeSmartFillConfig commands.
|
|
10
|
+
VALID_KEYS = %i[value maxLength embeddingEnabled].freeze
|
|
10
11
|
|
|
11
12
|
def self.build(**kwargs)
|
|
12
13
|
{ plainText: kwargs.slice(*VALID_KEYS).compact }
|
|
@@ -5,8 +5,9 @@ module Ecoportal
|
|
|
5
5
|
class WorkflowCommand
|
|
6
6
|
module EditFieldConfiguration
|
|
7
7
|
module RichText
|
|
8
|
-
SCHEMA_VERSION = '
|
|
9
|
-
|
|
8
|
+
SCHEMA_VERSION = '20260713'.freeze
|
|
9
|
+
# 20260713: smartFillConfiguration moved out to dedicated add/edit/removeSmartFillConfig commands.
|
|
10
|
+
VALID_KEYS = %i[content markdown embeddingEnabled].freeze
|
|
10
11
|
|
|
11
12
|
def self.build(**kwargs)
|
|
12
13
|
{ richText: kwargs.slice(*VALID_KEYS).compact }
|
|
@@ -5,8 +5,9 @@ module Ecoportal
|
|
|
5
5
|
class WorkflowCommand
|
|
6
6
|
module EditFieldConfiguration
|
|
7
7
|
module Select
|
|
8
|
-
SCHEMA_VERSION = '
|
|
9
|
-
|
|
8
|
+
SCHEMA_VERSION = '20260713'.freeze
|
|
9
|
+
# 20260713: smartFillConfiguration moved out to dedicated add/edit/removeSmartFillConfig commands.
|
|
10
|
+
VALID_KEYS = %i[dataType multiple flat other otherDesc].freeze
|
|
10
11
|
|
|
11
12
|
def self.build(**kwargs)
|
|
12
13
|
{ select: kwargs.slice(*VALID_KEYS).compact }
|
|
@@ -4,8 +4,9 @@ module Ecoportal
|
|
|
4
4
|
module Input
|
|
5
5
|
class WorkflowCommand
|
|
6
6
|
module MoveField
|
|
7
|
-
SCHEMA_VERSION = '
|
|
8
|
-
|
|
7
|
+
SCHEMA_VERSION = '20260713'.freeze
|
|
8
|
+
# 20260713: gained anchor-based positioning (anchorId/anchorPosition).
|
|
9
|
+
VALID_KEYS = %i[id sectionId column anchorId anchorPosition].freeze
|
|
9
10
|
|
|
10
11
|
def self.build(**kwargs)
|
|
11
12
|
kwargs.slice(*VALID_KEYS).compact
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
module Ecoportal
|
|
2
|
+
module API
|
|
3
|
+
class GraphQL
|
|
4
|
+
module Input
|
|
5
|
+
class WorkflowCommand
|
|
6
|
+
# `WorkflowMoveViewableFieldInput` — reorders a viewable field on a People data field.
|
|
7
|
+
# Same shape as AddViewableField minus `schemaFieldType` (the field already exists, so
|
|
8
|
+
# its type is known server-side). See AddViewableField for why these three commands
|
|
9
|
+
# replaced the removed `people.add/removeViewableFields` arrays.
|
|
10
|
+
module MoveViewableField
|
|
11
|
+
SCHEMA_VERSION = '20260725'.freeze
|
|
12
|
+
VALID_KEYS = %i[dataFieldId schemaFieldId anchorId anchorPosition].freeze
|
|
13
|
+
ANCHOR_POSITIONS = AddViewableField::ANCHOR_POSITIONS
|
|
14
|
+
|
|
15
|
+
def self.build(data_field_id:, schema_field_id:, **kwargs)
|
|
16
|
+
position = kwargs[:anchorPosition]
|
|
17
|
+
unless position.nil? || ANCHOR_POSITIONS.include?(position.to_s)
|
|
18
|
+
raise ArgumentError,
|
|
19
|
+
"Invalid anchorPosition #{position.inspect}: " \
|
|
20
|
+
"expected one of #{ANCHOR_POSITIONS.join(', ')}"
|
|
21
|
+
end
|
|
22
|
+
|
|
23
|
+
{
|
|
24
|
+
dataFieldId: data_field_id,
|
|
25
|
+
schemaFieldId: schema_field_id
|
|
26
|
+
}.merge(kwargs.slice(:anchorId, :anchorPosition).compact)
|
|
27
|
+
end
|
|
28
|
+
end
|
|
29
|
+
end
|
|
30
|
+
end
|
|
31
|
+
end
|
|
32
|
+
end
|
|
33
|
+
end
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
module Ecoportal
|
|
2
|
+
module API
|
|
3
|
+
class GraphQL
|
|
4
|
+
module Input
|
|
5
|
+
class WorkflowCommand
|
|
6
|
+
# 20260713
|
|
7
|
+
module RemoveChecklistFieldItem
|
|
8
|
+
SCHEMA_VERSION = '20260713'.freeze
|
|
9
|
+
VALID_KEYS = %i[dataFieldId itemId].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 RemoveSmartFillConfig
|
|
8
|
+
SCHEMA_VERSION = '20260713'.freeze
|
|
9
|
+
VALID_KEYS = %i[dataFieldId].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,21 @@
|
|
|
1
|
+
module Ecoportal
|
|
2
|
+
module API
|
|
3
|
+
class GraphQL
|
|
4
|
+
module Input
|
|
5
|
+
class WorkflowCommand
|
|
6
|
+
# `WorkflowRemoveViewableFieldInput` — removes a viewable field from a People data
|
|
7
|
+
# field. Both keys are required (`ID!`). Replaces the removed
|
|
8
|
+
# `people.removeViewableFields` array — see AddViewableField.
|
|
9
|
+
module RemoveViewableField
|
|
10
|
+
SCHEMA_VERSION = '20260725'.freeze
|
|
11
|
+
VALID_KEYS = %i[dataFieldId schemaFieldId].freeze
|
|
12
|
+
|
|
13
|
+
def self.build(data_field_id:, schema_field_id:)
|
|
14
|
+
{ dataFieldId: data_field_id, schemaFieldId: schema_field_id }
|
|
15
|
+
end
|
|
16
|
+
end
|
|
17
|
+
end
|
|
18
|
+
end
|
|
19
|
+
end
|
|
20
|
+
end
|
|
21
|
+
end
|
|
@@ -4,8 +4,9 @@ module Ecoportal
|
|
|
4
4
|
module Input
|
|
5
5
|
class WorkflowCommand
|
|
6
6
|
module ReorderForces
|
|
7
|
-
SCHEMA_VERSION = '
|
|
8
|
-
|
|
7
|
+
SCHEMA_VERSION = '20260713'.freeze
|
|
8
|
+
# 20260713: `after`/`before` replaced by anchor-based positioning.
|
|
9
|
+
VALID_KEYS = %i[forceId anchorId anchorPosition].freeze
|
|
9
10
|
|
|
10
11
|
def self.build(**kwargs)
|
|
11
12
|
kwargs.slice(*VALID_KEYS).compact
|
|
@@ -4,8 +4,9 @@ module Ecoportal
|
|
|
4
4
|
module Input
|
|
5
5
|
class WorkflowCommand
|
|
6
6
|
module ReorderSection
|
|
7
|
-
SCHEMA_VERSION = '
|
|
8
|
-
|
|
7
|
+
SCHEMA_VERSION = '20260713'.freeze
|
|
8
|
+
# 20260713: `after`/`before` replaced by anchor-based positioning.
|
|
9
|
+
VALID_KEYS = %i[sectionId stageId anchorId anchorPosition].freeze
|
|
9
10
|
|
|
10
11
|
def self.build(**kwargs)
|
|
11
12
|
kwargs.slice(*VALID_KEYS).compact
|
|
@@ -6,9 +6,17 @@ module Ecoportal
|
|
|
6
6
|
SCHEMA_VERSION = '20260605'.freeze
|
|
7
7
|
|
|
8
8
|
COMMAND_MAP = {
|
|
9
|
-
#
|
|
10
|
-
|
|
11
|
-
|
|
9
|
+
# Template settings (20260713 — supersede the removed page-level editPage/editPageCreatorPermissions)
|
|
10
|
+
editTemplateBasicSettings: 'Ecoportal::API::GraphQL::Input::WorkflowCommand::EditTemplateBasicSettings',
|
|
11
|
+
editTemplateAdvancedSettings: 'Ecoportal::API::GraphQL::Input::WorkflowCommand::EditTemplateAdvancedSettings',
|
|
12
|
+
editTemplateCreatorPermissions: 'Ecoportal::API::GraphQL::Input::WorkflowCommand::EditTemplateCreatorPermissions',
|
|
13
|
+
editTemplateDescriptions: 'Ecoportal::API::GraphQL::Input::WorkflowCommand::EditTemplateDescriptions',
|
|
14
|
+
# Cross-version template identity (the series key) — see the input class for the
|
|
15
|
+
# publish-swap rule that makes it usable as an entity id across versions.
|
|
16
|
+
editTemplateContainerUid: 'Ecoportal::API::GraphQL::Input::WorkflowCommand::EditTemplateContainerUid',
|
|
17
|
+
createPublicConfig: 'Ecoportal::API::GraphQL::Input::WorkflowCommand::CreatePublicConfig',
|
|
18
|
+
editPublicConfig: 'Ecoportal::API::GraphQL::Input::WorkflowCommand::EditPublicConfig',
|
|
19
|
+
archivePublicConfig: 'Ecoportal::API::GraphQL::Input::WorkflowCommand::ArchivePublicConfig',
|
|
12
20
|
# Stage structural
|
|
13
21
|
addStage: 'Ecoportal::API::GraphQL::Input::WorkflowCommand::AddStage',
|
|
14
22
|
removeStage: 'Ecoportal::API::GraphQL::Input::WorkflowCommand::RemoveStage',
|
|
@@ -91,6 +99,19 @@ module Ecoportal
|
|
|
91
99
|
removeField: 'Ecoportal::API::GraphQL::Input::WorkflowCommand::RemoveField',
|
|
92
100
|
# Field config
|
|
93
101
|
editFieldConfiguration: 'Ecoportal::API::GraphQL::Input::WorkflowCommand::EditFieldConfiguration',
|
|
102
|
+
# Viewable fields on People data fields (20260725) — replaced the REMOVED
|
|
103
|
+
# `people.addViewableFields`/`removeViewableFields` arrays; see AddViewableField.
|
|
104
|
+
addViewableField: 'Ecoportal::API::GraphQL::Input::WorkflowCommand::AddViewableField',
|
|
105
|
+
moveViewableField: 'Ecoportal::API::GraphQL::Input::WorkflowCommand::MoveViewableField',
|
|
106
|
+
removeViewableField: 'Ecoportal::API::GraphQL::Input::WorkflowCommand::RemoveViewableField',
|
|
107
|
+
# Checklist field items (20260713)
|
|
108
|
+
addChecklistFieldItem: 'Ecoportal::API::GraphQL::Input::WorkflowCommand::AddChecklistFieldItem',
|
|
109
|
+
editChecklistFieldItem: 'Ecoportal::API::GraphQL::Input::WorkflowCommand::EditChecklistFieldItem',
|
|
110
|
+
removeChecklistFieldItem: 'Ecoportal::API::GraphQL::Input::WorkflowCommand::RemoveChecklistFieldItem',
|
|
111
|
+
# Smart-fill config (20260713 — extracted from field-config inputs)
|
|
112
|
+
addSmartFillConfig: 'Ecoportal::API::GraphQL::Input::WorkflowCommand::AddSmartFillConfig',
|
|
113
|
+
editSmartFillConfig: 'Ecoportal::API::GraphQL::Input::WorkflowCommand::EditSmartFillConfig',
|
|
114
|
+
removeSmartFillConfig: 'Ecoportal::API::GraphQL::Input::WorkflowCommand::RemoveSmartFillConfig',
|
|
94
115
|
# Select options
|
|
95
116
|
addSelectFieldOption: 'Ecoportal::API::GraphQL::Input::WorkflowCommand::AddSelectFieldOption',
|
|
96
117
|
editSelectFieldOption: 'Ecoportal::API::GraphQL::Input::WorkflowCommand::EditSelectFieldOption',
|
|
@@ -147,8 +168,20 @@ module Ecoportal
|
|
|
147
168
|
end
|
|
148
169
|
end
|
|
149
170
|
|
|
150
|
-
require_relative 'workflow_command/
|
|
151
|
-
require_relative 'workflow_command/
|
|
171
|
+
require_relative 'workflow_command/edit_template_basic_settings'
|
|
172
|
+
require_relative 'workflow_command/edit_template_advanced_settings'
|
|
173
|
+
require_relative 'workflow_command/edit_template_creator_permissions'
|
|
174
|
+
require_relative 'workflow_command/edit_template_descriptions'
|
|
175
|
+
require_relative 'workflow_command/edit_template_container_uid'
|
|
176
|
+
require_relative 'workflow_command/create_public_config'
|
|
177
|
+
require_relative 'workflow_command/edit_public_config'
|
|
178
|
+
require_relative 'workflow_command/archive_public_config'
|
|
179
|
+
require_relative 'workflow_command/add_checklist_field_item'
|
|
180
|
+
require_relative 'workflow_command/edit_checklist_field_item'
|
|
181
|
+
require_relative 'workflow_command/remove_checklist_field_item'
|
|
182
|
+
require_relative 'workflow_command/add_smart_fill_config'
|
|
183
|
+
require_relative 'workflow_command/edit_smart_fill_config'
|
|
184
|
+
require_relative 'workflow_command/remove_smart_fill_config'
|
|
152
185
|
require_relative 'workflow_command/add_stage'
|
|
153
186
|
require_relative 'workflow_command/remove_stage'
|
|
154
187
|
require_relative 'workflow_command/edit_stage'
|
|
@@ -237,9 +270,14 @@ require_relative 'workflow_command/remove_binding'
|
|
|
237
270
|
require_relative 'workflow_command/add_linked_helper'
|
|
238
271
|
require_relative 'workflow_command/edit_linked_helper'
|
|
239
272
|
require_relative 'workflow_command/remove_linked_helper'
|
|
273
|
+
require_relative 'workflow_command/add_viewable_field'
|
|
274
|
+
require_relative 'workflow_command/move_viewable_field'
|
|
275
|
+
require_relative 'workflow_command/remove_viewable_field'
|
|
276
|
+
require_relative 'workflow_command/field_config/action_list'
|
|
240
277
|
require_relative 'workflow_command/field_config/contractor_entities'
|
|
241
278
|
require_relative 'workflow_command/field_config/cross_reference'
|
|
242
279
|
require_relative 'workflow_command/field_config/date'
|
|
280
|
+
require_relative 'workflow_command/field_config/file'
|
|
243
281
|
require_relative 'workflow_command/field_config/gauge'
|
|
244
282
|
require_relative 'workflow_command/field_config/image_gallery'
|
|
245
283
|
require_relative 'workflow_command/field_config/location_field'
|
|
@@ -16,6 +16,7 @@ require_relative 'input/contractor_entity'
|
|
|
16
16
|
require_relative 'input/action'
|
|
17
17
|
require_relative 'input/page'
|
|
18
18
|
require_relative 'input/delta_input'
|
|
19
|
+
require_relative 'input/date_range'
|
|
19
20
|
require_relative 'input/search_conf'
|
|
20
21
|
|
|
21
22
|
require_relative 'input/register'
|
|
@@ -6,6 +6,12 @@ module Ecoportal
|
|
|
6
6
|
include Concerns::PageCompat
|
|
7
7
|
include Concerns::DataFieldAccess
|
|
8
8
|
|
|
9
|
+
# Page-level leaf arrays (`otherTags`, whole-set `locations`) are cascaded
|
|
10
|
+
# attributes the default DiffService cannot see. LeafDiffService diffs them
|
|
11
|
+
# inline (full-set replace) while still cascading into real nested models
|
|
12
|
+
# (e.g. a phased page's `stages`). See Diffable::LeafDiffService.
|
|
13
|
+
DIFF_CLASS = Ecoportal::API::Common::GraphQL::Model::Diffable::LeafDiffService
|
|
14
|
+
|
|
9
15
|
passkey :id
|
|
10
16
|
passthrough :name, :uid
|
|
11
17
|
passthrough :icon
|
|
@@ -15,7 +21,6 @@ module Ecoportal
|
|
|
15
21
|
# class_resolver :force_class, 'Ecoportal::API::GraphQL::Base::Force'
|
|
16
22
|
# class_resolver :task_class, 'Ecoportal::API::GraphQL::Interface::Task'
|
|
17
23
|
# class_resolver :theme_class, 'Ecoportal::API::GraphQL::Base::Theme'
|
|
18
|
-
# class_resolver :template_class, 'Ecoportal::API::GraphQL::Base::Template'
|
|
19
24
|
# class_resolver :register_class, 'Ecoportal::API::GraphQL::Base::Register'
|
|
20
25
|
class_resolver :organization_class, 'Ecoportal::API::GraphQL::Base::Organization'
|
|
21
26
|
|
|
@@ -41,7 +46,6 @@ module Ecoportal
|
|
|
41
46
|
# embeds_one :taskPriority, klass: 'BasePage::TaskPriorityEnum', read_only: true
|
|
42
47
|
passthrough :taskPriority
|
|
43
48
|
|
|
44
|
-
|
|
45
49
|
passthrough :patchVer
|
|
46
50
|
|
|
47
51
|
passboolean :draft, :archived
|
|
@@ -78,7 +82,36 @@ module Ecoportal
|
|
|
78
82
|
# the CreateFromTemplateInput preview. nil for fetched/persisted pages.
|
|
79
83
|
attr_accessor :_compat_source_template_id
|
|
80
84
|
|
|
81
|
-
#
|
|
85
|
+
# The narrow `Template` type (NOT the template page — see Base::Template for the
|
|
86
|
+
# asymmetry). Populated only for template pages; nil for records. Carries
|
|
87
|
+
# `templateContainerUid`, the cross-version series key.
|
|
88
|
+
class_resolver :template_class, 'Ecoportal::API::GraphQL::Model::Template::Information'
|
|
89
|
+
|
|
90
|
+
# Deliberately NOT `embeds_one ..., read_only: true`, and this is not a style choice:
|
|
91
|
+
# `read_only` does not keep a mutated child out of the parent's diff. With `embeds_one`,
|
|
92
|
+
# `page.template.templateContainerUid = 'x'` yields
|
|
93
|
+
# `as_update => { id:, template: { templateContainerUid: 'x' } }` — but `UpdatePageInput`
|
|
94
|
+
# has NO `template` member, so that would push a key `updatePage` cannot accept. The
|
|
95
|
+
# only writer for the series key is the `editTemplateContainerUid` workflow command.
|
|
96
|
+
#
|
|
97
|
+
# So this follows the same on-demand read-only pattern as `#forces` above, over a COPY of
|
|
98
|
+
# the sub-doc: the returned model is a genuine dead end — writes to it cannot reach
|
|
99
|
+
# `doc`, cannot dirty the page, and cannot leak into an update.
|
|
100
|
+
def template
|
|
101
|
+
return nil unless (raw = doc['template'])
|
|
102
|
+
|
|
103
|
+
@template ||= template_class.new(
|
|
104
|
+
Ecoportal::API::Common::GraphQL::HashHelpers.deep_dup(raw)
|
|
105
|
+
)
|
|
106
|
+
end
|
|
107
|
+
|
|
108
|
+
# Convenience reader for the cross-version series key — nil unless this page is a
|
|
109
|
+
# template AND the read selected `template { templateContainerUid }` (CommonPageUnion
|
|
110
|
+
# does). Many versions may share one uid; only one may be published at a time.
|
|
111
|
+
def templateContainerUid
|
|
112
|
+
template&.templateContainerUid
|
|
113
|
+
end
|
|
114
|
+
|
|
82
115
|
# embeds_many :registers, klass: :register_class, read_only: true
|
|
83
116
|
# embeds_one :organization, klass: :organization_class, read_only: true
|
|
84
117
|
|
|
@@ -18,6 +18,23 @@ module Ecoportal
|
|
|
18
18
|
embeds_many :nodes, klass: :node_class
|
|
19
19
|
embeds_one :pageInfo, klass: Base::PageInfo
|
|
20
20
|
|
|
21
|
+
# Bind a connection subclass to its concrete node type.
|
|
22
|
+
#
|
|
23
|
+
# The base `embeds_many :nodes, klass: :node_class` builds a SINGLE dynamic
|
|
24
|
+
# `CollectionModel` ("nodes::node_class") that every subclass inherits and shares.
|
|
25
|
+
# The v2 collection layer memoizes the resolved class on that shared collection
|
|
26
|
+
# (items_klass.rb:62-63), so the FIRST connection instantiated in a process poisons
|
|
27
|
+
# every other connection's instance `nodes` typing (e.g. a MinimalDashboard connection
|
|
28
|
+
# returning AuthLog nodes). Declaring `embeds_many :nodes` per subclass with the concrete
|
|
29
|
+
# class gives each subclass its OWN collection ("nodes::Model::X") bound to a real Class —
|
|
30
|
+
# no shared symbol, nothing to memoize wrongly.
|
|
31
|
+
#
|
|
32
|
+
# Use `nodes_of Model::X` in a subclass instead of `class_resolver :node_class, Model::X`.
|
|
33
|
+
def self.nodes_of(klass)
|
|
34
|
+
class_resolver :node_class, klass
|
|
35
|
+
embeds_many :nodes, klass: klass
|
|
36
|
+
end
|
|
37
|
+
|
|
21
38
|
def empty?
|
|
22
39
|
count < 1
|
|
23
40
|
end
|