ecoportal-api-graphql 1.3.5 → 1.3.9
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/.ai-assistance/bridge/CLAUDE.md +338 -0
- data/.ai-assistance/bridge/archive/.gitkeep +0 -0
- data/.ai-assistance/bridge/archive/oscar-a1b2c3d-gitlab-mcp-doc-update.inbox.md +29 -0
- data/.ai-assistance/bridge/archive/oscar-a1b2c3d-gitlab-mcp-doc-update.outbox.md +18 -0
- data/.ai-assistance/bridge/archive/oscar-c912c25-gemini-design-review.inbox.md +42 -0
- data/.ai-assistance/bridge/archive/oscar-c912c25-gemini-design-review.outbox.md +115 -0
- data/.ai-assistance/bridge/context/gemini-review-prompt.txt +48 -0
- data/.ai-assistance/bridge/context/gemini-review-response.md +104 -0
- data/.ai-assistance/bridge/context/project.md +42 -0
- data/.ai-assistance/bridge/inbox/.gitkeep +0 -0
- data/.ai-assistance/bridge/outbox/.gitkeep +0 -0
- data/.ai-assistance/bridge/outbox/request-for-standards-discovery.md +48 -0
- data/.ai-assistance/bridge/queue/.gitkeep +1 -0
- data/.ai-assistance/capabilities/CLAUDE.md +27 -0
- data/.ai-assistance/capabilities/assumptions-log.md +80 -0
- data/.ai-assistance/capabilities/code.md +47 -0
- data/.ai-assistance/capabilities/connectors.md +37 -0
- data/.ai-assistance/capabilities/cowork.md +55 -0
- data/.ai-assistance/code/OVERVIEW.md +155 -0
- data/.ai-assistance/code/data_fields.md +242 -0
- data/.ai-assistance/code/dependencies.md +151 -0
- data/.ai-assistance/code/diff_as_input.md +234 -0
- data/.ai-assistance/code/diff_service_deep_dive.md +192 -0
- data/.ai-assistance/code/ecoPortal_architecture/00_overview_and_index.md +55 -0
- data/.ai-assistance/code/ecoPortal_architecture/01_terminology_dictionary.md +181 -0
- data/.ai-assistance/code/ecoPortal_architecture/02_data_model.md +192 -0
- data/.ai-assistance/code/ecoPortal_architecture/03_api_layers.md +147 -0
- data/.ai-assistance/code/ecoPortal_architecture/04_graphql_queries_mutations.md +277 -0
- data/.ai-assistance/code/ecoPortal_architecture/05_page_workflows.md +200 -0
- data/.ai-assistance/code/ecoPortal_architecture/06_search_and_filters.md +228 -0
- data/.ai-assistance/code/ecoPortal_architecture/07_data_fields.md +197 -0
- data/.ai-assistance/code/ecoPortal_architecture/08_stages_sections.md +243 -0
- data/.ai-assistance/code/ecoPortal_architecture/09_people_contractors_locations.md +196 -0
- data/.ai-assistance/code/ecoPortal_architecture/10_forces_workflow_builder.md +132 -0
- data/.ai-assistance/code/ecoPortal_architecture/11_integration_gems.md +187 -0
- data/.ai-assistance/code/ecoPortal_architecture/12_ai_documentation_sources_gaps.md +236 -0
- data/.ai-assistance/code/ecoPortal_architecture/13_ai_infrastructure.md +183 -0
- data/.ai-assistance/code/ecoportal_schema_reference.md +240 -0
- data/.ai-assistance/code/graphql_domain_knowledge.md +230 -0
- data/.ai-assistance/code/refactoring/datafield-readwrite-shape-asymmetry.md +71 -0
- data/.ai-assistance/code/refactoring/opportunities.md +251 -0
- data/.ai-assistance/code/schema_analysis.md +321 -0
- data/.ai-assistance/code/search_filters.md +868 -0
- data/.ai-assistance/code/spec_coverage.md +73 -0
- data/.ai-assistance/code/workflow-command-guide.md +438 -0
- data/.ai-assistance/code/workflow-space.md +353 -0
- data/.ai-assistance/conventions/CLAUDE.md +30 -0
- data/.ai-assistance/conventions/code-working-tree-protocol.md +199 -0
- data/.ai-assistance/conventions/gitignore-rules.md +42 -0
- data/.ai-assistance/conventions/permission-guidance.md +120 -0
- data/.ai-assistance/integrations/README.md +70 -0
- data/.ai-assistance/integrations/gitkraken-mcp.md +107 -0
- data/.ai-assistance/integrations/gitlab-mcp.md +123 -0
- data/.ai-assistance/integrations/local-git.md +60 -0
- data/.ai-assistance/local_paths.example.md +17 -0
- data/.ai-assistance/projects/TODO.md +97 -0
- data/.ai-assistance/projects/api-v2-to-graphql-migration/DECISIONS.md +168 -0
- data/.ai-assistance/projects/api-v2-to-graphql-migration/INTENT.md +60 -0
- data/.ai-assistance/projects/api-v2-to-graphql-migration/TODO.md +267 -0
- data/.ai-assistance/projects/api-v2-to-graphql-migration/UPSTREAM.md +53 -0
- data/.ai-assistance/projects/api-v2-to-graphql-migration/notes/csv-template-pipeline-design.md +102 -0
- data/.ai-assistance/projects/api-v2-to-graphql-migration/notes/cutover-usecase-gap-audit.md +139 -0
- data/.ai-assistance/projects/dynamic-model-generation/INTENT.md +93 -0
- data/.ai-assistance/projects/eco-helpers-compat/INTENT.md +244 -0
- data/.ai-assistance/projects/eco-helpers-compat/MIGRATION_GUIDE.md +266 -0
- data/.ai-assistance/projects/eco-helpers-compat/TODO.md +86 -0
- data/.ai-assistance/projects/ecoportal-api-v2-doublemodel-review/INTENT.md +101 -0
- data/.ai-assistance/projects/graphql-agent/GAP_ANALYSIS.md +177 -0
- data/.ai-assistance/projects/ooze-graphql-native-migration/DECISIONS.md +161 -0
- data/.ai-assistance/projects/ooze-graphql-native-migration/INTENT.md +125 -0
- data/.ai-assistance/projects/ooze-graphql-native-migration/RISKS.md +126 -0
- data/.ai-assistance/projects/ooze-graphql-native-migration/TODO.md +256 -0
- data/.ai-assistance/projects/ooze-graphql-native-migration/analysis/2026-06-30-cutover-workflow-deep-review.md +122 -0
- data/.ai-assistance/projects/ooze-graphql-native-migration/analysis/2026-07-01-forces-via-workflow-commands-miss-rca.md +148 -0
- data/.ai-assistance/projects/page-model/DECISIONS.md +245 -0
- data/.ai-assistance/projects/page-model/TODO.md +190 -0
- data/.ai-assistance/projects/search-filter-builder/INTENT.md +107 -0
- data/.ai-assistance/projects/search-filter-builder/TODO.md +131 -0
- data/.ai-assistance/projects/template-maintenance/DESIGN.md +134 -0
- data/.ai-assistance/projects/workflow-space/TODO.md +213 -0
- data/.ai-assistance/reinstall-claude-desktop-windows.md +136 -0
- data/.ai-assistance/scripts/CLAUDE.md +150 -0
- data/.ai-assistance/scripts/bridge-init.sh +86 -0
- data/.ai-assistance/scripts/bridge-status.sh +44 -0
- data/.ai-assistance/scripts/capabilities-check.ts +104 -0
- data/.ai-assistance/scripts/check-outbox.sh +43 -0
- data/.ai-assistance/scripts/dep_graph.rb +91 -0
- data/.ai-assistance/scripts/lock-acquire.sh +103 -0
- data/.ai-assistance/scripts/lock-multi.sh +124 -0
- data/.ai-assistance/scripts/lock-queue.sh +94 -0
- data/.ai-assistance/scripts/setup-mcps.test.ts +188 -0
- data/.ai-assistance/scripts/setup-mcps.ts +234 -0
- data/.ai-assistance/scripts/task-complete.ts +74 -0
- data/.ai-assistance/scripts/task-create.ts +75 -0
- data/.ai-assistance/scripts/task-read.ts +125 -0
- data/.ai-assistance/scripts/token-logger.js +220 -0
- data/.ai-assistance/scripts/token-report.ts +158 -0
- data/.ai-assistance/scripts/token-session-start.js +66 -0
- data/.ai-assistance/skills/ai-instructions/SKILL.md +48 -0
- data/.ai-assistance/skills/code-specs/SKILL.md +69 -0
- data/.ai-assistance/skills/corporate-policies/SKILL.md +201 -0
- data/.ai-assistance/skills/dep-graph/SKILL.md +139 -0
- data/.ai-assistance/skills/ep-ai-manager/SKILL.md +417 -0
- data/.ai-assistance/skills/gemini-assist/SKILL.md +63 -0
- data/.ai-assistance/skills/gemini-assist/gemini-mcp-server.js +205 -0
- data/.ai-assistance/skills/gemini-assist/gemini_ask.py +1 -0
- data/.ai-assistance/skills/gemini-assist/gemini_ask.rb +240 -0
- data/.ai-assistance/skills/gemini-assist/prompts/cycle_end_review.txt +25 -0
- data/.ai-assistance/skills/graphql-schema-analysis/SKILL.md +261 -0
- data/.ai-assistance/skills/project-cycle/SKILL.md +177 -0
- data/.ai-assistance/skills/refactor/SKILL.md +62 -0
- data/.ai-assistance/skills/rubocop/SKILL.md +93 -0
- data/.ai-assistance/skills/ruby-scripting/SKILL.md +215 -0
- data/.ai-assistance/skills/spec-generation/SKILL.md +72 -0
- data/.ai-assistance/standards-version.json +21 -0
- data/.ai-assistance/token-budget.json +32 -0
- data/.ai-assistance/version.json +39 -0
- data/.claude/settings.json +146 -0
- data/.env.example +18 -0
- data/.gitattributes +15 -0
- data/.gitignore +13 -0
- data/.rubocop.yml +121 -97
- data/CHANGELOG.md +673 -477
- data/CLAUDE.md +232 -0
- data/Gemfile +30 -6
- data/Rakefile +90 -38
- data/docs/worklog.md +574 -0
- data/ecoportal-api-graphql.gemspec +40 -40
- data/lib/ecoportal/api/common/graphql/CLAUDE.md +36 -0
- data/lib/ecoportal/api/common/graphql/client.rb +1 -1
- data/lib/ecoportal/api/common/graphql/http_client.rb +35 -3
- data/lib/ecoportal/api/common/graphql/model/CLAUDE.md +28 -0
- data/lib/ecoportal/api/common/graphql/model/as_input.rb +8 -5
- data/lib/ecoportal/api/common/graphql/model/diffable/classic_diff_service.rb +3 -1
- data/lib/ecoportal/api/common/graphql/model/diffable/diff_service.rb +31 -23
- data/lib/ecoportal/api/common/graphql/model/diffable/hash_diff_nesting.rb +54 -1
- data/lib/ecoportal/api/graphql/CLAUDE.md +37 -0
- data/lib/ecoportal/api/graphql/base/CLAUDE.md +50 -0
- data/lib/ecoportal/api/graphql/base/ai_summary_version.rb +17 -0
- data/lib/ecoportal/api/graphql/base/delta_result.rb +16 -0
- data/lib/ecoportal/api/graphql/base/force/binding.rb +19 -0
- data/lib/ecoportal/api/graphql/base/force/binding_collection.rb +62 -0
- data/lib/ecoportal/api/graphql/base/force/collection.rb +47 -0
- data/lib/ecoportal/api/graphql/base/force.rb +65 -0
- data/lib/ecoportal/api/graphql/base/kickstand/job.rb +17 -0
- data/lib/ecoportal/api/graphql/base/kickstand/workflow.rb +18 -0
- data/lib/ecoportal/api/graphql/base/kickstand.rb +13 -0
- data/lib/ecoportal/api/graphql/base/page/basic.rb +38 -0
- data/lib/ecoportal/api/graphql/base/page/data_field/actions_list.rb +9 -0
- data/lib/ecoportal/api/graphql/base/page/data_field/ai_summary.rb +18 -0
- data/lib/ecoportal/api/graphql/base/page/data_field/checklist.rb +29 -0
- data/lib/ecoportal/api/graphql/base/page/data_field/collection.rb +112 -0
- data/lib/ecoportal/api/graphql/base/page/data_field/contractor_entities.rb +28 -0
- data/lib/ecoportal/api/graphql/base/page/data_field/cross_reference.rb +54 -0
- data/lib/ecoportal/api/graphql/base/page/data_field/date_field.rb +23 -0
- data/lib/ecoportal/api/graphql/base/page/data_field/file_field.rb +25 -0
- data/lib/ecoportal/api/graphql/base/page/data_field/gauge.rb +19 -0
- data/lib/ecoportal/api/graphql/base/page/data_field/geo.rb +24 -0
- data/lib/ecoportal/api/graphql/base/page/data_field/image_gallery.rb +24 -0
- data/lib/ecoportal/api/graphql/base/page/data_field/law.rb +8 -0
- data/lib/ecoportal/api/graphql/base/page/data_field/mailbox.rb +9 -0
- data/lib/ecoportal/api/graphql/base/page/data_field/number.rb +20 -0
- data/lib/ecoportal/api/graphql/base/page/data_field/people.rb +35 -0
- data/lib/ecoportal/api/graphql/base/page/data_field/plain_text.rb +17 -0
- data/lib/ecoportal/api/graphql/base/page/data_field/rich_text.rb +26 -0
- data/lib/ecoportal/api/graphql/base/page/data_field/select.rb +41 -0
- data/lib/ecoportal/api/graphql/base/page/data_field/signature.rb +9 -0
- data/lib/ecoportal/api/graphql/base/page/data_field/smart_fill.rb +17 -0
- data/lib/ecoportal/api/graphql/base/page/data_field/table.rb +9 -0
- data/lib/ecoportal/api/graphql/base/page/data_field/tag_field.rb +21 -0
- data/lib/ecoportal/api/graphql/base/page/data_field.rb +137 -12
- data/lib/ecoportal/api/graphql/base/page/phased/stage.rb +68 -14
- data/lib/ecoportal/api/graphql/base/page/phased.rb +1 -0
- data/lib/ecoportal/api/graphql/base/page/section.rb +36 -0
- data/lib/ecoportal/api/graphql/base/page/section_collection.rb +79 -0
- data/lib/ecoportal/api/graphql/base/page.rb +2 -0
- data/lib/ecoportal/api/graphql/base/pages_workflow/action_type_selection.rb +17 -0
- data/lib/ecoportal/api/graphql/base/pages_workflow/callback_type.rb +28 -0
- data/lib/ecoportal/api/graphql/base/pages_workflow/command_change.rb +17 -0
- data/lib/ecoportal/api/graphql/base/pages_workflow/command_change_message.rb +15 -0
- data/lib/ecoportal/api/graphql/base/pages_workflow/command_es_change.rb +17 -0
- data/lib/ecoportal/api/graphql/base/pages_workflow/command_interface.rb +36 -0
- data/lib/ecoportal/api/graphql/base/pages_workflow/email_config.rb +18 -0
- data/lib/ecoportal/api/graphql/base/pages_workflow/escalation_level.rb +19 -0
- data/lib/ecoportal/api/graphql/base/pages_workflow/in_system_config.rb +16 -0
- data/lib/ecoportal/api/graphql/base/pages_workflow/mailbox_field_selection.rb +17 -0
- data/lib/ecoportal/api/graphql/base/pages_workflow/operation_interface.rb +39 -0
- data/lib/ecoportal/api/graphql/base/pages_workflow/operations/assign_to.rb +27 -0
- data/lib/ecoportal/api/graphql/base/pages_workflow/operations/create_page.rb +21 -0
- data/lib/ecoportal/api/graphql/base/pages_workflow/operations/send_notification.rb +30 -0
- data/lib/ecoportal/api/graphql/base/pages_workflow/people_field_selection.rb +17 -0
- data/lib/ecoportal/api/graphql/base/pages_workflow/recipient_config.rb +34 -0
- data/lib/ecoportal/api/graphql/base/pages_workflow/register_field.rb +17 -0
- data/lib/ecoportal/api/graphql/base/pages_workflow/task_config_selection.rb +17 -0
- data/lib/ecoportal/api/graphql/base/pages_workflow/time_delay_config.rb +16 -0
- data/lib/ecoportal/api/graphql/base/pages_workflow/trigger_interface.rb +26 -0
- data/lib/ecoportal/api/graphql/base/pages_workflow/triggers/conditional_logic.rb +17 -0
- data/lib/ecoportal/api/graphql/base/pages_workflow/user_selection.rb +16 -0
- data/lib/ecoportal/api/graphql/base/pages_workflow.rb +35 -0
- data/lib/ecoportal/api/graphql/base/preset_view.rb +17 -0
- data/lib/ecoportal/api/graphql/base/preview_page.rb +23 -0
- data/lib/ecoportal/api/graphql/base/register.rb +18 -0
- data/lib/ecoportal/api/graphql/base.rb +11 -0
- data/lib/ecoportal/api/graphql/builder/CLAUDE.md +65 -0
- data/lib/ecoportal/api/graphql/builder/kickstand.rb +73 -0
- data/lib/ecoportal/api/graphql/builder/page.rb +210 -41
- data/lib/ecoportal/api/graphql/builder/register/preset_view.rb +84 -0
- data/lib/ecoportal/api/graphql/builder/register.rb +27 -19
- data/lib/ecoportal/api/graphql/builder/template.rb +80 -0
- data/lib/ecoportal/api/graphql/builder.rb +2 -0
- data/lib/ecoportal/api/graphql/compat/filter_translator.rb +107 -0
- data/lib/ecoportal/api/graphql/compat/page_reference.rb +23 -0
- data/lib/ecoportal/api/graphql/compat/pages.rb +212 -0
- data/lib/ecoportal/api/graphql/compat/registers.rb +84 -0
- data/lib/ecoportal/api/graphql/compat/response.rb +35 -0
- data/lib/ecoportal/api/graphql/compat/search_results.rb +33 -0
- data/lib/ecoportal/api/graphql/compat/stage_collection.rb +70 -0
- data/lib/ecoportal/api/graphql/compat/stage_view.rb +76 -0
- data/lib/ecoportal/api/graphql/compat.rb +17 -0
- data/lib/ecoportal/api/graphql/concerns/data_field_access.rb +71 -0
- data/lib/ecoportal/api/graphql/concerns/deprecation.rb +20 -0
- data/lib/ecoportal/api/graphql/concerns/fragment_definitions.rb +21 -28
- data/lib/ecoportal/api/graphql/concerns/page_compat.rb +51 -0
- data/lib/ecoportal/api/graphql/concerns/snake_camel_access.rb +60 -0
- data/lib/ecoportal/api/graphql/concerns.rb +4 -0
- data/lib/ecoportal/api/graphql/connection/page.rb +11 -0
- data/lib/ecoportal/api/graphql/connection/pages_workflow_command.rb +13 -0
- data/lib/ecoportal/api/graphql/connection/preset_view.rb +11 -0
- data/lib/ecoportal/api/graphql/connection/preview_page.rb +11 -0
- data/lib/ecoportal/api/graphql/connection.rb +4 -0
- data/lib/ecoportal/api/graphql/file_upload/client.rb +181 -0
- data/lib/ecoportal/api/graphql/file_upload.rb +10 -0
- data/lib/ecoportal/api/graphql/fragment/action.rb +1 -1
- data/lib/ecoportal/api/graphql/fragment/action_category.rb +1 -1
- data/lib/ecoportal/api/graphql/fragment/contractor_entity.rb +1 -1
- data/lib/ecoportal/api/graphql/fragment/force.rb +30 -0
- data/lib/ecoportal/api/graphql/fragment/location_draft.rb +2 -2
- data/lib/ecoportal/api/graphql/fragment/location_node.rb +1 -1
- data/lib/ecoportal/api/graphql/fragment/locations_error.rb +1 -1
- data/lib/ecoportal/api/graphql/fragment/page.rb +85 -0
- data/lib/ecoportal/api/graphql/fragment/pages/common_page_union.rb +395 -0
- data/lib/ecoportal/api/graphql/fragment/pages.rb +15 -0
- data/lib/ecoportal/api/graphql/fragment/pages_workflow.rb +172 -0
- data/lib/ecoportal/api/graphql/fragment/pagination.rb +1 -1
- data/lib/ecoportal/api/graphql/fragment.rb +37 -27
- data/lib/ecoportal/api/graphql/input/contractor_entity/update.rb +25 -0
- data/lib/ecoportal/api/graphql/input/delta_input.rb +16 -0
- data/lib/ecoportal/api/graphql/input/page/archive.rb +14 -0
- data/lib/ecoportal/api/graphql/input/page/build_from_template.rb +13 -0
- data/lib/ecoportal/api/graphql/input/page/create_draft.rb +13 -0
- data/lib/ecoportal/api/graphql/input/page/create_from_template.rb +18 -0
- data/lib/ecoportal/api/graphql/input/page/delete_draft.rb +13 -0
- data/lib/ecoportal/api/graphql/input/page/publish_draft.rb +13 -0
- data/lib/ecoportal/api/graphql/input/page/review_task.rb +14 -0
- data/lib/ecoportal/api/graphql/input/page/unarchive.rb +14 -0
- data/lib/ecoportal/api/graphql/input/page/update.rb +140 -0
- data/lib/ecoportal/api/graphql/input/page.rb +26 -0
- data/lib/ecoportal/api/graphql/input/preset_view/create.rb +18 -0
- data/lib/ecoportal/api/graphql/input/preset_view/permission.rb +16 -0
- data/lib/ecoportal/api/graphql/input/preset_view/update.rb +16 -0
- data/lib/ecoportal/api/graphql/input/preset_view.rb +14 -0
- data/lib/ecoportal/api/graphql/input/register/create.rb +18 -0
- data/lib/ecoportal/api/graphql/input/register/update.rb +15 -0
- data/lib/ecoportal/api/graphql/input/register.rb +13 -0
- data/lib/ecoportal/api/graphql/input/search_conf/ai_generator.rb +234 -0
- data/lib/ecoportal/api/graphql/input/search_conf.rb +367 -0
- data/lib/ecoportal/api/graphql/input/variable_binding.rb +20 -0
- data/lib/ecoportal/api/graphql/input/workflow_command/add_action_tag.rb +18 -0
- data/lib/ecoportal/api/graphql/input/workflow_command/add_binding.rb +18 -0
- data/lib/ecoportal/api/graphql/input/workflow_command/add_comment_tagging_user_group.rb +18 -0
- data/lib/ecoportal/api/graphql/input/workflow_command/add_default_direct_strategy_user.rb +18 -0
- data/lib/ecoportal/api/graphql/input/workflow_command/add_default_strategy.rb +18 -0
- data/lib/ecoportal/api/graphql/input/workflow_command/add_direct_strategy_user.rb +18 -0
- data/lib/ecoportal/api/graphql/input/workflow_command/add_field.rb +18 -0
- data/lib/ecoportal/api/graphql/input/workflow_command/add_force.rb +18 -0
- data/lib/ecoportal/api/graphql/input/workflow_command/add_gauge_field_stop.rb +19 -0
- data/lib/ecoportal/api/graphql/input/workflow_command/add_linked_field_config.rb +23 -0
- data/lib/ecoportal/api/graphql/input/workflow_command/add_linked_helper.rb +18 -0
- data/lib/ecoportal/api/graphql/input/workflow_command/add_operation.rb +18 -0
- data/lib/ecoportal/api/graphql/input/workflow_command/add_operation_direct_strategy_user.rb +18 -0
- data/lib/ecoportal/api/graphql/input/workflow_command/add_operation_strategy.rb +18 -0
- data/lib/ecoportal/api/graphql/input/workflow_command/add_recipient_action_type.rb +18 -0
- data/lib/ecoportal/api/graphql/input/workflow_command/add_recipient_filter.rb +18 -0
- data/lib/ecoportal/api/graphql/input/workflow_command/add_recipient_people_field.rb +18 -0
- data/lib/ecoportal/api/graphql/input/workflow_command/add_recipient_task_config.rb +18 -0
- data/lib/ecoportal/api/graphql/input/workflow_command/add_recipient_user.rb +18 -0
- data/lib/ecoportal/api/graphql/input/workflow_command/add_scheduled_callback.rb +23 -0
- data/lib/ecoportal/api/graphql/input/workflow_command/add_scheduled_callback_action.rb +18 -0
- data/lib/ecoportal/api/graphql/input/workflow_command/add_section.rb +18 -0
- data/lib/ecoportal/api/graphql/input/workflow_command/add_select_field_option.rb +19 -0
- data/lib/ecoportal/api/graphql/input/workflow_command/add_stage.rb +18 -0
- data/lib/ecoportal/api/graphql/input/workflow_command/add_stage_section.rb +18 -0
- data/lib/ecoportal/api/graphql/input/workflow_command/add_stage_tag.rb +18 -0
- data/lib/ecoportal/api/graphql/input/workflow_command/add_strategy.rb +18 -0
- data/lib/ecoportal/api/graphql/input/workflow_command/add_task.rb +18 -0
- data/lib/ecoportal/api/graphql/input/workflow_command/add_task_assignment_user_group.rb +18 -0
- data/lib/ecoportal/api/graphql/input/workflow_command/add_workflow_callback.rb +18 -0
- data/lib/ecoportal/api/graphql/input/workflow_command/collapse_section.rb +18 -0
- data/lib/ecoportal/api/graphql/input/workflow_command/edit_binding.rb +18 -0
- data/lib/ecoportal/api/graphql/input/workflow_command/edit_creator_permissions.rb +18 -0
- data/lib/ecoportal/api/graphql/input/workflow_command/edit_default_strategy.rb +18 -0
- data/lib/ecoportal/api/graphql/input/workflow_command/edit_field_configuration.rb +21 -0
- data/lib/ecoportal/api/graphql/input/workflow_command/edit_force.rb +18 -0
- data/lib/ecoportal/api/graphql/input/workflow_command/edit_gauge_field_stop.rb +19 -0
- data/lib/ecoportal/api/graphql/input/workflow_command/edit_linked_field_config.rb +19 -0
- data/lib/ecoportal/api/graphql/input/workflow_command/edit_linked_helper.rb +18 -0
- data/lib/ecoportal/api/graphql/input/workflow_command/edit_operation.rb +18 -0
- data/lib/ecoportal/api/graphql/input/workflow_command/edit_operation_strategy.rb +18 -0
- data/lib/ecoportal/api/graphql/input/workflow_command/edit_page.rb +28 -0
- data/lib/ecoportal/api/graphql/input/workflow_command/edit_page_creator_permissions.rb +18 -0
- data/lib/ecoportal/api/graphql/input/workflow_command/edit_reminder.rb +18 -0
- data/lib/ecoportal/api/graphql/input/workflow_command/edit_required_sign_offs.rb +18 -0
- data/lib/ecoportal/api/graphql/input/workflow_command/edit_restrict_comment_tagging.rb +18 -0
- data/lib/ecoportal/api/graphql/input/workflow_command/edit_restrict_task_assignment.rb +18 -0
- data/lib/ecoportal/api/graphql/input/workflow_command/edit_scheduled_callback.rb +22 -0
- data/lib/ecoportal/api/graphql/input/workflow_command/edit_section_header.rb +18 -0
- data/lib/ecoportal/api/graphql/input/workflow_command/edit_select_field_option.rb +19 -0
- data/lib/ecoportal/api/graphql/input/workflow_command/edit_stage.rb +18 -0
- data/lib/ecoportal/api/graphql/input/workflow_command/edit_strategy.rb +18 -0
- data/lib/ecoportal/api/graphql/input/workflow_command/edit_task_due.rb +18 -0
- data/lib/ecoportal/api/graphql/input/workflow_command/edit_trigger.rb +18 -0
- data/lib/ecoportal/api/graphql/input/workflow_command/expand_section.rb +18 -0
- data/lib/ecoportal/api/graphql/input/workflow_command/field_config/contractor_entities.rb +24 -0
- data/lib/ecoportal/api/graphql/input/workflow_command/field_config/cross_reference.rb +23 -0
- data/lib/ecoportal/api/graphql/input/workflow_command/field_config/date.rb +20 -0
- data/lib/ecoportal/api/graphql/input/workflow_command/field_config/gauge.rb +20 -0
- data/lib/ecoportal/api/graphql/input/workflow_command/field_config/image_gallery.rb +20 -0
- data/lib/ecoportal/api/graphql/input/workflow_command/field_config/location_field.rb +24 -0
- data/lib/ecoportal/api/graphql/input/workflow_command/field_config/people.rb +24 -0
- data/lib/ecoportal/api/graphql/input/workflow_command/field_config/plain_text.rb +20 -0
- data/lib/ecoportal/api/graphql/input/workflow_command/field_config/rich_text.rb +20 -0
- data/lib/ecoportal/api/graphql/input/workflow_command/field_config/select.rb +20 -0
- data/lib/ecoportal/api/graphql/input/workflow_command/field_config/signature.rb +20 -0
- data/lib/ecoportal/api/graphql/input/workflow_command/field_config/table.rb +25 -0
- data/lib/ecoportal/api/graphql/input/workflow_command/move_field.rb +18 -0
- data/lib/ecoportal/api/graphql/input/workflow_command/move_stage.rb +18 -0
- data/lib/ecoportal/api/graphql/input/workflow_command/remove_action_tag.rb +18 -0
- data/lib/ecoportal/api/graphql/input/workflow_command/remove_binding.rb +18 -0
- data/lib/ecoportal/api/graphql/input/workflow_command/remove_callback.rb +18 -0
- data/lib/ecoportal/api/graphql/input/workflow_command/remove_comment_tagging_user_group.rb +18 -0
- data/lib/ecoportal/api/graphql/input/workflow_command/remove_default_direct_strategy_user.rb +18 -0
- data/lib/ecoportal/api/graphql/input/workflow_command/remove_default_strategy.rb +18 -0
- data/lib/ecoportal/api/graphql/input/workflow_command/remove_direct_strategy_user.rb +18 -0
- data/lib/ecoportal/api/graphql/input/workflow_command/remove_field.rb +18 -0
- data/lib/ecoportal/api/graphql/input/workflow_command/remove_force.rb +18 -0
- data/lib/ecoportal/api/graphql/input/workflow_command/remove_gauge_field_stop.rb +17 -0
- data/lib/ecoportal/api/graphql/input/workflow_command/remove_linked_field_config.rb +17 -0
- data/lib/ecoportal/api/graphql/input/workflow_command/remove_linked_helper.rb +18 -0
- data/lib/ecoportal/api/graphql/input/workflow_command/remove_operation.rb +18 -0
- data/lib/ecoportal/api/graphql/input/workflow_command/remove_operation_direct_strategy_user.rb +18 -0
- data/lib/ecoportal/api/graphql/input/workflow_command/remove_operation_strategy.rb +18 -0
- data/lib/ecoportal/api/graphql/input/workflow_command/remove_recipient_action_type.rb +18 -0
- data/lib/ecoportal/api/graphql/input/workflow_command/remove_recipient_filter.rb +18 -0
- data/lib/ecoportal/api/graphql/input/workflow_command/remove_recipient_people_field.rb +18 -0
- data/lib/ecoportal/api/graphql/input/workflow_command/remove_recipient_task_config.rb +18 -0
- data/lib/ecoportal/api/graphql/input/workflow_command/remove_recipient_user.rb +18 -0
- data/lib/ecoportal/api/graphql/input/workflow_command/remove_scheduled_callback.rb +18 -0
- data/lib/ecoportal/api/graphql/input/workflow_command/remove_section.rb +18 -0
- data/lib/ecoportal/api/graphql/input/workflow_command/remove_select_field_option.rb +17 -0
- data/lib/ecoportal/api/graphql/input/workflow_command/remove_stage.rb +18 -0
- data/lib/ecoportal/api/graphql/input/workflow_command/remove_stage_section.rb +18 -0
- data/lib/ecoportal/api/graphql/input/workflow_command/remove_stage_tag.rb +18 -0
- data/lib/ecoportal/api/graphql/input/workflow_command/remove_strategy.rb +18 -0
- data/lib/ecoportal/api/graphql/input/workflow_command/remove_task.rb +18 -0
- data/lib/ecoportal/api/graphql/input/workflow_command/remove_task_assignment_user_group.rb +18 -0
- data/lib/ecoportal/api/graphql/input/workflow_command/remove_task_due.rb +18 -0
- data/lib/ecoportal/api/graphql/input/workflow_command/remove_task_priority_level.rb +18 -0
- data/lib/ecoportal/api/graphql/input/workflow_command/reorder_forces.rb +18 -0
- data/lib/ecoportal/api/graphql/input/workflow_command/reorder_section.rb +18 -0
- data/lib/ecoportal/api/graphql/input/workflow_command.rb +251 -0
- data/lib/ecoportal/api/graphql/input.rb +8 -0
- data/lib/ecoportal/api/graphql/interface/base_page.rb +100 -58
- data/lib/ecoportal/api/graphql/interface/location_structure/nodes.rb +27 -28
- data/lib/ecoportal/api/graphql/logic/base_model.rb +2 -0
- data/lib/ecoportal/api/graphql/logic/base_query.rb +45 -2
- data/lib/ecoportal/api/graphql/logic/input.rb +15 -0
- data/lib/ecoportal/api/graphql/model/ai_summary_version.rb +10 -0
- data/lib/ecoportal/api/graphql/model/organization.rb +65 -55
- data/lib/ecoportal/api/graphql/model/page/basic.rb +14 -0
- data/lib/ecoportal/api/graphql/model/page/phased.rb +82 -20
- data/lib/ecoportal/api/graphql/model/page.rb +1 -0
- data/lib/ecoportal/api/graphql/model/page_union.rb +21 -0
- data/lib/ecoportal/api/graphql/model/pages_workflow.rb +20 -0
- data/lib/ecoportal/api/graphql/model/preset_view.rb +10 -0
- data/lib/ecoportal/api/graphql/model/preview_page.rb +10 -0
- data/lib/ecoportal/api/graphql/model/register.rb +10 -0
- data/lib/ecoportal/api/graphql/model.rb +8 -0
- data/lib/ecoportal/api/graphql/mutation/ai_summary/generate.rb +45 -0
- data/lib/ecoportal/api/graphql/mutation/ai_summary/submit_feedback.rb +40 -0
- data/lib/ecoportal/api/graphql/mutation/ai_summary.rb +13 -0
- data/lib/ecoportal/api/graphql/mutation/kickstand/bulk_update_jobs.rb +43 -0
- data/lib/ecoportal/api/graphql/mutation/kickstand/bulk_update_workflows.rb +43 -0
- data/lib/ecoportal/api/graphql/mutation/kickstand/fail_job.rb +39 -0
- data/lib/ecoportal/api/graphql/mutation/kickstand/fail_workflow.rb +39 -0
- data/lib/ecoportal/api/graphql/mutation/kickstand/start_job.rb +39 -0
- data/lib/ecoportal/api/graphql/mutation/kickstand/start_workflow.rb +39 -0
- data/lib/ecoportal/api/graphql/mutation/kickstand/stop_workflow.rb +39 -0
- data/lib/ecoportal/api/graphql/mutation/kickstand.rb +18 -0
- data/lib/ecoportal/api/graphql/mutation/location_structure/apply_commands.rb +3 -3
- data/lib/ecoportal/api/graphql/mutation/location_structure/draft/add_commands.rb +2 -2
- data/lib/ecoportal/api/graphql/mutation/location_structure/draft/create.rb +2 -2
- data/lib/ecoportal/api/graphql/mutation/location_structure/draft/drop_bad_commands.rb +3 -3
- data/lib/ecoportal/api/graphql/mutation/location_structure/draft/publish.rb +3 -3
- data/lib/ecoportal/api/graphql/mutation/page/approve_review_task.rb +40 -0
- data/lib/ecoportal/api/graphql/mutation/page/archive.rb +40 -0
- data/lib/ecoportal/api/graphql/mutation/page/batch_update_review_task.rb +40 -0
- data/lib/ecoportal/api/graphql/mutation/page/build_from_template.rb +50 -0
- data/lib/ecoportal/api/graphql/mutation/page/create_draft.rb +40 -0
- data/lib/ecoportal/api/graphql/mutation/page/create_from_template.rb +43 -0
- data/lib/ecoportal/api/graphql/mutation/page/delete_draft.rb +40 -0
- data/lib/ecoportal/api/graphql/mutation/page/execute_force_commands.rb +69 -0
- data/lib/ecoportal/api/graphql/mutation/page/execute_workflow_commands.rb +51 -0
- data/lib/ecoportal/api/graphql/mutation/page/publish_draft.rb +40 -0
- data/lib/ecoportal/api/graphql/mutation/page/reject_review_task.rb +40 -0
- data/lib/ecoportal/api/graphql/mutation/page/restart_review_task.rb +40 -0
- data/lib/ecoportal/api/graphql/mutation/page/unarchive.rb +40 -0
- data/lib/ecoportal/api/graphql/mutation/page/undo_review_task.rb +40 -0
- data/lib/ecoportal/api/graphql/mutation/page/update.rb +40 -0
- data/lib/ecoportal/api/graphql/mutation/page/update_variable_bindings.rb +44 -0
- data/lib/ecoportal/api/graphql/mutation/page.rb +28 -0
- data/lib/ecoportal/api/graphql/mutation/preset_view/create.rb +35 -0
- data/lib/ecoportal/api/graphql/mutation/preset_view/destroy.rb +35 -0
- data/lib/ecoportal/api/graphql/mutation/preset_view/permission.rb +37 -0
- data/lib/ecoportal/api/graphql/mutation/preset_view/update.rb +35 -0
- data/lib/ecoportal/api/graphql/mutation/preset_view.rb +15 -0
- data/lib/ecoportal/api/graphql/mutation/register/create.rb +35 -0
- data/lib/ecoportal/api/graphql/mutation/register/destroy.rb +35 -0
- data/lib/ecoportal/api/graphql/mutation/register/update.rb +35 -0
- data/lib/ecoportal/api/graphql/mutation/register.rb +14 -0
- data/lib/ecoportal/api/graphql/mutation/smart_fill/generate.rb +36 -0
- data/lib/ecoportal/api/graphql/mutation/smart_fill/submit_feedback.rb +40 -0
- data/lib/ecoportal/api/graphql/mutation/smart_fill.rb +13 -0
- data/lib/ecoportal/api/graphql/mutation/template/create.rb +39 -0
- data/lib/ecoportal/api/graphql/mutation/template/create_related_page.rb +46 -0
- data/lib/ecoportal/api/graphql/mutation/template/destroy_related_page.rb +43 -0
- data/lib/ecoportal/api/graphql/mutation/template/publish.rb +39 -0
- data/lib/ecoportal/api/graphql/mutation/template/unpublish.rb +39 -0
- data/lib/ecoportal/api/graphql/mutation/template/update.rb +43 -0
- data/lib/ecoportal/api/graphql/mutation/template/update_information.rb +43 -0
- data/lib/ecoportal/api/graphql/mutation/template.rb +18 -0
- data/lib/ecoportal/api/graphql/mutation.rb +8 -0
- data/lib/ecoportal/api/graphql/payload/ai_summary_generate.rb +12 -0
- data/lib/ecoportal/api/graphql/payload/execute_workflow_commands.rb +36 -0
- data/lib/ecoportal/api/graphql/payload/force_commands.rb +31 -0
- data/lib/ecoportal/api/graphql/payload/kickstand/bulk_update_jobs.rb +36 -0
- data/lib/ecoportal/api/graphql/payload/kickstand/bulk_update_workflows.rb +36 -0
- data/lib/ecoportal/api/graphql/payload/kickstand/job.rb +13 -0
- data/lib/ecoportal/api/graphql/payload/kickstand/workflow.rb +13 -0
- data/lib/ecoportal/api/graphql/payload/kickstand.rb +15 -0
- data/lib/ecoportal/api/graphql/payload/location_structure/draft/create.rb +33 -34
- data/lib/ecoportal/api/graphql/payload/ok_payload.rb +21 -0
- data/lib/ecoportal/api/graphql/payload/page/archive.rb +13 -0
- data/lib/ecoportal/api/graphql/payload/page/build_from_template.rb +13 -0
- data/lib/ecoportal/api/graphql/payload/page/create_from_template.rb +13 -0
- data/lib/ecoportal/api/graphql/payload/page/draft.rb +13 -0
- data/lib/ecoportal/api/graphql/payload/page/review_task.rb +13 -0
- data/lib/ecoportal/api/graphql/payload/page/unarchive.rb +13 -0
- data/lib/ecoportal/api/graphql/payload/page/update.rb +13 -0
- data/lib/ecoportal/api/graphql/payload/page/update_variable_bindings.rb +13 -0
- data/lib/ecoportal/api/graphql/payload/page.rb +19 -0
- data/lib/ecoportal/api/graphql/payload/preset_view.rb +11 -0
- data/lib/ecoportal/api/graphql/payload/register.rb +11 -0
- data/lib/ecoportal/api/graphql/payload/template/create.rb +13 -0
- data/lib/ecoportal/api/graphql/payload/template/create_related_page.rb +13 -0
- data/lib/ecoportal/api/graphql/payload/template/destroy_related_page.rb +13 -0
- data/lib/ecoportal/api/graphql/payload/template/publish.rb +13 -0
- data/lib/ecoportal/api/graphql/payload/template/unpublish.rb +13 -0
- data/lib/ecoportal/api/graphql/payload/template/update.rb +13 -0
- data/lib/ecoportal/api/graphql/payload/template/update_information.rb +13 -0
- data/lib/ecoportal/api/graphql/payload/template.rb +18 -0
- data/lib/ecoportal/api/graphql/payload.rb +11 -0
- data/lib/ecoportal/api/graphql/query/action.rb +1 -1
- data/lib/ecoportal/api/graphql/query/action_categories.rb +1 -1
- data/lib/ecoportal/api/graphql/query/actions.rb +2 -2
- data/lib/ecoportal/api/graphql/query/contractor_entities.rb +1 -1
- data/lib/ecoportal/api/graphql/query/file_upload_signature.rb +76 -0
- data/lib/ecoportal/api/graphql/query/location_structure/draft.rb +2 -2
- data/lib/ecoportal/api/graphql/query/location_structure.rb +1 -1
- data/lib/ecoportal/api/graphql/query/location_structures.rb +1 -1
- data/lib/ecoportal/api/graphql/query/page.rb +45 -0
- data/lib/ecoportal/api/graphql/query/page_delta.rb +47 -0
- data/lib/ecoportal/api/graphql/query/page_with_forces.rb +43 -0
- data/lib/ecoportal/api/graphql/query/pages.rb +59 -0
- data/lib/ecoportal/api/graphql/query/pages_workflow_commands.rb +59 -0
- data/lib/ecoportal/api/graphql/query/register_preset_views.rb +78 -0
- data/lib/ecoportal/api/graphql/query/register_preview_pages.rb +83 -0
- data/lib/ecoportal/api/graphql/query/templates.rb +53 -0
- data/lib/ecoportal/api/graphql/query.rb +11 -0
- data/lib/ecoportal/api/graphql.rb +60 -2
- data/lib/ecoportal/api/graphql_version.rb +5 -5
- data/scripts/auto-worker-scheduler.sh +386 -0
- data/tests/contractor_entity_create.rb +19 -19
- data/tests/contractor_entity_udpate.rb +20 -20
- data/tests/dump_page_model.rb +74 -0
- data/tests/loc_structure_get.rb +1 -2
- data/tests/loc_structure_update.rb +51 -51
- data/tests/loc_structures_get.rb +15 -15
- metadata +436 -5
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
module Ecoportal
|
|
2
|
+
module API
|
|
3
|
+
class GraphQL
|
|
4
|
+
module Input
|
|
5
|
+
class Page
|
|
6
|
+
# Maps CreateFromTemplateInput.
|
|
7
|
+
# dataFields.updates is passed as a raw array — typed support is Phase E.
|
|
8
|
+
class CreateFromTemplate < Logic::Input
|
|
9
|
+
passthrough :templateId, :showHiddenData, :stageId, :submit, :attach, :draft
|
|
10
|
+
passthrough :clientMutationId
|
|
11
|
+
passthrough :dataFields # raw: { updates: [...typed field hashes...] }
|
|
12
|
+
embeds_one :page, klass: 'Ecoportal::API::GraphQL::Input::Page'
|
|
13
|
+
end
|
|
14
|
+
end
|
|
15
|
+
end
|
|
16
|
+
end
|
|
17
|
+
end
|
|
18
|
+
end
|
|
@@ -0,0 +1,140 @@
|
|
|
1
|
+
module Ecoportal
|
|
2
|
+
module API
|
|
3
|
+
class GraphQL
|
|
4
|
+
module Input
|
|
5
|
+
class Page
|
|
6
|
+
class Update < Logic::Input
|
|
7
|
+
passkey :id
|
|
8
|
+
passthrough :patchVer, :publish, :clientMutationId
|
|
9
|
+
|
|
10
|
+
PAGE_FIELD_KEYS = Input::Page::PAGE_FIELD_KEYS
|
|
11
|
+
|
|
12
|
+
class << self
|
|
13
|
+
# Builds UpdatePageInput from a page model.
|
|
14
|
+
# Returns nil when there are no changes and no operation is requested.
|
|
15
|
+
# patchVer is always included when present (required for concurrency control).
|
|
16
|
+
#
|
|
17
|
+
# Options:
|
|
18
|
+
# stage_id: ID — target a specific stage (required for stage submit/close-out)
|
|
19
|
+
# submit: Boolean — submit the stage (triggers task transitions server-side)
|
|
20
|
+
# publish: Boolean — publish a draft page
|
|
21
|
+
# show_hidden_data: Boolean — include hidden data in the mutation response
|
|
22
|
+
# task: Hash — raw page-task command, passed through verbatim. Variants:
|
|
23
|
+
# { completePageTask: { forcedComplete:, signOff:, notes: } } — complete the page task
|
|
24
|
+
# { reviewPageTask: { signOff:, notes: } } — sign off / annotate a review task
|
|
25
|
+
# complete_page_task: Boolean|Hash — sugar for task: { completePageTask: ... }.
|
|
26
|
+
# true → { completePageTask: {} } (bare submit, no inline review).
|
|
27
|
+
# Hash → inline CompletePageInput fields (snake_case keys):
|
|
28
|
+
# { sign_off:, forced_complete:, notes: } →
|
|
29
|
+
# { completePageTask: { signOff:, forcedComplete:, notes: } }.
|
|
30
|
+
# Use { sign_off: true } to submit AND sign-off in ONE call —
|
|
31
|
+
# this advances a stage whose config has a review task (the
|
|
32
|
+
# server auto-approves the review inline). Distinct from the
|
|
33
|
+
# sign_off:/review_notes: sugar below, which targets reviewPageTask
|
|
34
|
+
# (the separate review-approval path).
|
|
35
|
+
# sign_off: Boolean — sugar: task: { reviewPageTask: { signOff: ... } }
|
|
36
|
+
# review_notes: String — sugar: adds notes: to the reviewPageTask
|
|
37
|
+
# location_ids: [ID] — set page locations (PageInput.locations); the
|
|
38
|
+
# model's locations embed is read_only, so this is
|
|
39
|
+
# the way to write them
|
|
40
|
+
# client_mutation_id: String
|
|
41
|
+
def from_model(model, stage_id: nil, submit: nil, publish: nil, show_hidden_data: nil,
|
|
42
|
+
task: nil, complete_page_task: false, sign_off: nil, review_notes: nil,
|
|
43
|
+
location_ids: nil, client_mutation_id: '', **_kargs)
|
|
44
|
+
task = resolve_task(task, complete_page_task, sign_off, review_notes)
|
|
45
|
+
require_stage!(stage_id, submit, task)
|
|
46
|
+
page_input = (model.as_update || {}).slice(*PAGE_FIELD_KEYS)
|
|
47
|
+
# Page locations are read_only on the model (excluded from the as_update diff),
|
|
48
|
+
# so set them explicitly here → PageInput.locations = [LocationInput{ id }].
|
|
49
|
+
page_input = page_input.merge(locations: Array(location_ids).map { |lid| { id: lid } }) unless location_ids.nil?
|
|
50
|
+
data_fields = build_data_fields(model)
|
|
51
|
+
|
|
52
|
+
no_changes = page_input.empty? && data_fields.empty?
|
|
53
|
+
no_op = publish.nil? && submit.nil? && stage_id.nil? && task.nil?
|
|
54
|
+
return nil if no_changes && no_op
|
|
55
|
+
|
|
56
|
+
operation = {
|
|
57
|
+
stageId: stage_id,
|
|
58
|
+
submit: submit,
|
|
59
|
+
publish: publish,
|
|
60
|
+
showHiddenData: show_hidden_data,
|
|
61
|
+
task: task,
|
|
62
|
+
clientMutationId: (client_mutation_id.to_s.empty? ? nil : client_mutation_id)
|
|
63
|
+
}
|
|
64
|
+
build_input(model, page_input, data_fields, operation)
|
|
65
|
+
end
|
|
66
|
+
|
|
67
|
+
private
|
|
68
|
+
|
|
69
|
+
# Platform invariant: a stage submit / sign-off MUST target a specific stage.
|
|
70
|
+
# Page tasks (and the people-field permissions scoped to them) apply to ONE
|
|
71
|
+
# stage; without a stageId the server cannot route the submit to the stage the
|
|
72
|
+
# work was done on. Fail loudly here rather than silently omit stageId (the
|
|
73
|
+
# nil-guard in build_input would otherwise drop it — the exact bug that let an
|
|
74
|
+
# act-gov TOOCS submit go out stage-less). A plain field update or publish
|
|
75
|
+
# needs no stage and is unaffected.
|
|
76
|
+
def require_stage!(stage_id, submit, task)
|
|
77
|
+
return unless stage_id.nil?
|
|
78
|
+
return unless submit || task
|
|
79
|
+
|
|
80
|
+
raise ArgumentError,
|
|
81
|
+
'stageId is required to submit or complete a stage task (people-field ' \
|
|
82
|
+
'permissions are stage-scoped). Pass stage_id:, or operate via a stage ' \
|
|
83
|
+
'view (Compat::Pages#get(id, stage_id:) / OozeRedirect#stage) so the ' \
|
|
84
|
+
'submit targets the stage the work was done on.'
|
|
85
|
+
end
|
|
86
|
+
|
|
87
|
+
# Resolves the `task` command from an explicit hash or the convenience flags.
|
|
88
|
+
# An explicit `task:` always wins; otherwise complete_page_task / sign_off build it.
|
|
89
|
+
def resolve_task(task, complete_page_task, sign_off, review_notes)
|
|
90
|
+
return task unless task.nil?
|
|
91
|
+
return build_complete_page_task(complete_page_task) if complete_page_task
|
|
92
|
+
return nil if sign_off.nil? && review_notes.nil?
|
|
93
|
+
|
|
94
|
+
review = {}
|
|
95
|
+
review[:signOff] = sign_off unless sign_off.nil?
|
|
96
|
+
review[:notes] = review_notes unless review_notes.nil?
|
|
97
|
+
{ reviewPageTask: review }
|
|
98
|
+
end
|
|
99
|
+
|
|
100
|
+
# completePageTask command. `flag` is either `true` (bare completion) or a Hash of
|
|
101
|
+
# inline CompletePageInput options with snake_case keys (sign_off:, forced_complete:,
|
|
102
|
+
# notes:). Inline signOff advances a stage whose config has a review task — the server
|
|
103
|
+
# auto-approves the review in the same updatePage call.
|
|
104
|
+
def build_complete_page_task(flag)
|
|
105
|
+
return { completePageTask: {} } unless flag.is_a?(Hash)
|
|
106
|
+
|
|
107
|
+
inner = {}
|
|
108
|
+
inner[:forcedComplete] = flag[:forced_complete] unless flag[:forced_complete].nil?
|
|
109
|
+
inner[:signOff] = flag[:sign_off] unless flag[:sign_off].nil?
|
|
110
|
+
inner[:notes] = flag[:notes] unless flag[:notes].nil?
|
|
111
|
+
{ completePageTask: inner }
|
|
112
|
+
end
|
|
113
|
+
|
|
114
|
+
def build_input(model, page_input, data_fields, operation)
|
|
115
|
+
{ id: model.id }.tap do |input|
|
|
116
|
+
input[:patchVer] = model.patchVer if model.respond_to?(:patchVer) && !model.patchVer.nil?
|
|
117
|
+
input[:page] = page_input unless page_input.empty?
|
|
118
|
+
operation.each { |key, value| input[key] = value unless value.nil? }
|
|
119
|
+
input[:dataFields] = data_fields unless data_fields.empty?
|
|
120
|
+
end
|
|
121
|
+
end
|
|
122
|
+
|
|
123
|
+
def build_data_fields(model)
|
|
124
|
+
updates = model.respond_to?(:data_fields_updates) ? model.data_fields_updates : []
|
|
125
|
+
additions = model.respond_to?(:data_fields_additions) ? model.data_fields_additions : []
|
|
126
|
+
deletions = model.respond_to?(:data_fields_deletions) ? model.data_fields_deletions : []
|
|
127
|
+
|
|
128
|
+
{}.tap do |h|
|
|
129
|
+
h[:updates] = updates unless updates.empty?
|
|
130
|
+
h[:additions] = additions unless additions.empty?
|
|
131
|
+
h[:deletions] = deletions unless deletions.empty?
|
|
132
|
+
end
|
|
133
|
+
end
|
|
134
|
+
end
|
|
135
|
+
end
|
|
136
|
+
end
|
|
137
|
+
end
|
|
138
|
+
end
|
|
139
|
+
end
|
|
140
|
+
end
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
module Ecoportal
|
|
2
|
+
module API
|
|
3
|
+
class GraphQL
|
|
4
|
+
module Input
|
|
5
|
+
class Page < Logic::Input
|
|
6
|
+
# Fields that belong in PageInput (the nested sub-object of UpdatePageInput).
|
|
7
|
+
# Referenced by Input::Page::Update.from_model to extract the right keys from the diff.
|
|
8
|
+
PAGE_FIELD_KEYS = %i[name state taskPriority timeZone externalId locations otherTags].freeze
|
|
9
|
+
|
|
10
|
+
passthrough :name, :state, :taskPriority, :timeZone, :externalId
|
|
11
|
+
passarray :locations, :otherTags
|
|
12
|
+
end
|
|
13
|
+
end
|
|
14
|
+
end
|
|
15
|
+
end
|
|
16
|
+
end
|
|
17
|
+
|
|
18
|
+
require_relative 'page/update'
|
|
19
|
+
require_relative 'page/archive'
|
|
20
|
+
require_relative 'page/unarchive'
|
|
21
|
+
require_relative 'page/build_from_template'
|
|
22
|
+
require_relative 'page/create_from_template'
|
|
23
|
+
require_relative 'page/create_draft'
|
|
24
|
+
require_relative 'page/delete_draft'
|
|
25
|
+
require_relative 'page/publish_draft'
|
|
26
|
+
require_relative 'page/review_task'
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
module Ecoportal
|
|
2
|
+
module API
|
|
3
|
+
class GraphQL
|
|
4
|
+
module Input
|
|
5
|
+
class PresetView
|
|
6
|
+
# fieldConfigs: array of FieldConfigurationInput hashes
|
|
7
|
+
# { id:, key:, name:, weight:, type:, ... }
|
|
8
|
+
# sorter: { key:, direction:, missing: }
|
|
9
|
+
class Create < Logic::Input
|
|
10
|
+
passthrough :registerId, :name, :sorter
|
|
11
|
+
passboolean :customPresetView, :preview
|
|
12
|
+
passarray :fieldConfigs
|
|
13
|
+
end
|
|
14
|
+
end
|
|
15
|
+
end
|
|
16
|
+
end
|
|
17
|
+
end
|
|
18
|
+
end
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
module Ecoportal
|
|
2
|
+
module API
|
|
3
|
+
class GraphQL
|
|
4
|
+
module Input
|
|
5
|
+
class PresetView
|
|
6
|
+
# permissions: array of PresetViewPermissionInput hashes
|
|
7
|
+
# Each: { id:, level: "view"|"edit", to: { userId: } | { userGroupId: }, destroy: }
|
|
8
|
+
class Permission < Logic::Input
|
|
9
|
+
passkey :id
|
|
10
|
+
passarray :permissions
|
|
11
|
+
end
|
|
12
|
+
end
|
|
13
|
+
end
|
|
14
|
+
end
|
|
15
|
+
end
|
|
16
|
+
end
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
module Ecoportal
|
|
2
|
+
module API
|
|
3
|
+
class GraphQL
|
|
4
|
+
module Input
|
|
5
|
+
class PresetView < Logic::Input
|
|
6
|
+
end
|
|
7
|
+
end
|
|
8
|
+
end
|
|
9
|
+
end
|
|
10
|
+
end
|
|
11
|
+
|
|
12
|
+
require_relative 'preset_view/create'
|
|
13
|
+
require_relative 'preset_view/update'
|
|
14
|
+
require_relative 'preset_view/permission'
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
module Ecoportal
|
|
2
|
+
module API
|
|
3
|
+
class GraphQL
|
|
4
|
+
module Input
|
|
5
|
+
class Register
|
|
6
|
+
class Create < Logic::Input
|
|
7
|
+
passthrough :name, :iconName, :descriptionText, :moduleType, :registerStatus
|
|
8
|
+
passthrough :restrictedAmountOfTemplates
|
|
9
|
+
passboolean :shown, :creatable, :attachable, :permissioned
|
|
10
|
+
passboolean :contentShareable, :enableEmailOut, :isMobile
|
|
11
|
+
passboolean :restrictTemplatesAmount
|
|
12
|
+
passarray :filterTags, :userPermissions, :userGroupPermissions
|
|
13
|
+
end
|
|
14
|
+
end
|
|
15
|
+
end
|
|
16
|
+
end
|
|
17
|
+
end
|
|
18
|
+
end
|
|
@@ -0,0 +1,234 @@
|
|
|
1
|
+
module Ecoportal
|
|
2
|
+
module API
|
|
3
|
+
class GraphQL
|
|
4
|
+
module Input
|
|
5
|
+
class SearchConf
|
|
6
|
+
# AI-assisted filter generation — builds a SearchConf from a natural-language
|
|
7
|
+
# description using Claude (Anthropic API) with structured tool use output.
|
|
8
|
+
#
|
|
9
|
+
# Requires the `anthropic` gem to be available in the caller's environment.
|
|
10
|
+
# No hard dependency is added to ecoportal-api-graphql's gemspec.
|
|
11
|
+
#
|
|
12
|
+
# Usage:
|
|
13
|
+
# require 'anthropic'
|
|
14
|
+
#
|
|
15
|
+
# conf = SearchConf.from_description(
|
|
16
|
+
# "find active pages in the Safety register updated in the last month",
|
|
17
|
+
# api_key: ENV['ANTHROPIC_API_KEY'],
|
|
18
|
+
# register_id: 'REG_SAFETY_123'
|
|
19
|
+
# )
|
|
20
|
+
# # => #<SearchConf filters=[...] sorters=...>
|
|
21
|
+
#
|
|
22
|
+
# # Then use it:
|
|
23
|
+
# org.pages(searchConf: conf.to_h, first: 50)
|
|
24
|
+
#
|
|
25
|
+
# Options:
|
|
26
|
+
# api_key: Anthropic API key (default: ENV['ANTHROPIC_API_KEY'])
|
|
27
|
+
# model: Claude model ID (default: 'claude-sonnet-4-6')
|
|
28
|
+
# register_id: Scope results to this register (adds register_filter)
|
|
29
|
+
# context: Hash of extra context passed to the prompt (e.g. available states)
|
|
30
|
+
# validate: Boolean — if true, raises on ambiguous/empty result (default: false)
|
|
31
|
+
module AIGenerator
|
|
32
|
+
TOOL_NAME = 'build_search_conf'.freeze
|
|
33
|
+
DEFAULT_MODEL = 'claude-sonnet-4-6'.freeze
|
|
34
|
+
|
|
35
|
+
SYSTEM_PROMPT = <<~PROMPT.freeze
|
|
36
|
+
You are a search query translator for the EcoPortal GraphQL API.
|
|
37
|
+
Convert natural-language descriptions into structured searchConf filter specifications.
|
|
38
|
+
|
|
39
|
+
## Available filter operations (snake_case strings — case-sensitive)
|
|
40
|
+
|
|
41
|
+
| operation | params | notes |
|
|
42
|
+
|---------------------|---------------------------------------------|--------------------------------|
|
|
43
|
+
| exact_filter | key, value | equality match |
|
|
44
|
+
| one_of_filter | key, values (array) | any of N values |
|
|
45
|
+
| none_of_filter | key, values (array) | exclude all values |
|
|
46
|
+
| date_filter | key, gte, lte, time_zone (UTC default) | ISO8601 or mode |
|
|
47
|
+
| date_filter (mode) | key, mode, time_zone | modes: last_month, last_week, current_year, past, future, etc. |
|
|
48
|
+
| register_filter | ids (array) | scope to register(s) |
|
|
49
|
+
| has_any_filter | key | field has any non-empty value |
|
|
50
|
+
| match_filter | key, value | partial text match |
|
|
51
|
+
| and_filter | filters (array of filter objects) | explicit AND group |
|
|
52
|
+
| or_filter | filters (array of filter objects) | OR group |
|
|
53
|
+
| boolean_filter | key, value (true/false) | boolean field |
|
|
54
|
+
| numeric_range_filter| key, gte, lte | numeric bounds |
|
|
55
|
+
| isnt_exact_filter | key, value | negated equality |
|
|
56
|
+
|
|
57
|
+
## Common page field names (key values)
|
|
58
|
+
|
|
59
|
+
| fieldName | type | common values |
|
|
60
|
+
|-----------------|---------|----------------------------------------|
|
|
61
|
+
| state | string | "active", "inactive", "complete" |
|
|
62
|
+
| external_id | string | unique identifier |
|
|
63
|
+
| name | string | page name (use match_filter for partial)|
|
|
64
|
+
| creator_id | string | PersonMember ID |
|
|
65
|
+
| created_at | date | ISO8601 datetime |
|
|
66
|
+
| updated_at | date | ISO8601 datetime |
|
|
67
|
+
| all_location_ids| string | location node ID (includes ancestors) |
|
|
68
|
+
| location_id | string | exact location node ID |
|
|
69
|
+
| other_tags | string | tag string values |
|
|
70
|
+
| archived | boolean | true/false |
|
|
71
|
+
| draft | boolean | true/false |
|
|
72
|
+
|
|
73
|
+
## Rules
|
|
74
|
+
- Top-level filters array is implicitly AND — no need to wrap in and_filter unless nesting inside or_filter
|
|
75
|
+
- Use register_filter when a specific register is mentioned or provided in context
|
|
76
|
+
- Use date_filter with mode (e.g. "last_month") for relative dates; ISO8601 for absolute dates
|
|
77
|
+
- Default sort is created_at desc unless the user specifies otherwise
|
|
78
|
+
- If the description is too vague to produce a useful filter, produce an empty filters array and explain in the reasoning field
|
|
79
|
+
- snake_case operation names are MANDATORY — CamelCase returns no results silently
|
|
80
|
+
|
|
81
|
+
Call the build_search_conf tool with your result.
|
|
82
|
+
PROMPT
|
|
83
|
+
|
|
84
|
+
module_function
|
|
85
|
+
|
|
86
|
+
# Build a SearchConf from a natural-language description via Claude API.
|
|
87
|
+
def from_description(text, api_key: nil, model: DEFAULT_MODEL,
|
|
88
|
+
register_id: nil, context: {}, validate: false)
|
|
89
|
+
require_anthropic!
|
|
90
|
+
|
|
91
|
+
client = ::Anthropic::Client.new(api_key: api_key || ENV.fetch('ANTHROPIC_API_KEY'))
|
|
92
|
+
|
|
93
|
+
user_message = build_user_message(text, register_id: register_id, context: context)
|
|
94
|
+
response = client.messages.create(
|
|
95
|
+
model: model,
|
|
96
|
+
max_tokens: 1024,
|
|
97
|
+
system: SYSTEM_PROMPT,
|
|
98
|
+
tools: [SEARCH_CONF_TOOL],
|
|
99
|
+
messages: [{ role: 'user', content: user_message }]
|
|
100
|
+
)
|
|
101
|
+
|
|
102
|
+
result = extract_tool_result(response)
|
|
103
|
+
conf = build_search_conf(result, register_id: register_id)
|
|
104
|
+
|
|
105
|
+
if validate && conf.to_h.empty?
|
|
106
|
+
raise ArgumentError, "AI could not produce filters for: #{text.inspect}. " \
|
|
107
|
+
"Reasoning: #{result['reasoning']}"
|
|
108
|
+
end
|
|
109
|
+
|
|
110
|
+
conf
|
|
111
|
+
end
|
|
112
|
+
|
|
113
|
+
def require_anthropic!
|
|
114
|
+
require 'anthropic'
|
|
115
|
+
rescue LoadError
|
|
116
|
+
raise LoadError,
|
|
117
|
+
"SearchConf.from_description requires the 'anthropic' gem. " \
|
|
118
|
+
"Add `gem 'anthropic'` to your Gemfile and run `bundle install`."
|
|
119
|
+
end
|
|
120
|
+
|
|
121
|
+
def build_user_message(text, register_id:, context:)
|
|
122
|
+
parts = ["Convert this description to a searchConf filter: #{text.inspect}"]
|
|
123
|
+
parts << "Register ID to scope results: #{register_id}" if register_id
|
|
124
|
+
context.each { |k, v| parts << "Context — #{k}: #{v}" }
|
|
125
|
+
parts.join("\n")
|
|
126
|
+
end
|
|
127
|
+
|
|
128
|
+
def extract_tool_result(response)
|
|
129
|
+
tool_use = response.content.find { |b| b.type == 'tool_use' && b.name == TOOL_NAME }
|
|
130
|
+
raise "AI did not call #{TOOL_NAME} — response: #{response.content.map(&:type)}" unless tool_use
|
|
131
|
+
|
|
132
|
+
tool_use.input
|
|
133
|
+
end
|
|
134
|
+
|
|
135
|
+
def build_search_conf(result, register_id:)
|
|
136
|
+
conf = SearchConf.new
|
|
137
|
+
conf = apply_register(conf, result, register_id)
|
|
138
|
+
conf = apply_filters(conf, result['filters'])
|
|
139
|
+
conf = apply_sorters(conf, result['sorters'])
|
|
140
|
+
apply_query(conf, result['query'])
|
|
141
|
+
end
|
|
142
|
+
|
|
143
|
+
def apply_register(conf, result, register_id)
|
|
144
|
+
ids = result['register_ids']&.compact&.reject(&:empty?)
|
|
145
|
+
if ids && !ids.empty?
|
|
146
|
+
conf.filter(SearchConf::Register.new(*ids))
|
|
147
|
+
elsif register_id
|
|
148
|
+
conf.filter(SearchConf::Register.new(register_id))
|
|
149
|
+
else
|
|
150
|
+
conf
|
|
151
|
+
end
|
|
152
|
+
end
|
|
153
|
+
|
|
154
|
+
def apply_filters(conf, filters)
|
|
155
|
+
Array(filters).reduce(conf) do |c, f|
|
|
156
|
+
c.filter(SearchConf::RawFilter.new(f['operation'], **symbolize(f['params'] || {})))
|
|
157
|
+
end
|
|
158
|
+
end
|
|
159
|
+
|
|
160
|
+
def apply_sorters(conf, sorters)
|
|
161
|
+
Array(sorters).reduce(conf) do |c, s|
|
|
162
|
+
c.sort(s['key'].to_sym, s['direction']&.to_sym || :desc)
|
|
163
|
+
end
|
|
164
|
+
end
|
|
165
|
+
|
|
166
|
+
def apply_query(conf, query)
|
|
167
|
+
return conf unless query && !query.strip.empty?
|
|
168
|
+
|
|
169
|
+
conf.query(query)
|
|
170
|
+
end
|
|
171
|
+
|
|
172
|
+
def symbolize(hash)
|
|
173
|
+
hash.each_with_object({}) { |(k, v), h| h[k.to_sym] = v }
|
|
174
|
+
end
|
|
175
|
+
|
|
176
|
+
# JSON Schema for the tool — Claude must call this with the filter spec.
|
|
177
|
+
SEARCH_CONF_TOOL = {
|
|
178
|
+
name: TOOL_NAME,
|
|
179
|
+
description: 'Output a structured searchConf filter specification',
|
|
180
|
+
input_schema: {
|
|
181
|
+
type: 'object',
|
|
182
|
+
required: %w[filters],
|
|
183
|
+
properties: {
|
|
184
|
+
reasoning: {
|
|
185
|
+
type: 'string',
|
|
186
|
+
description: 'Brief explanation of the chosen filters'
|
|
187
|
+
},
|
|
188
|
+
register_ids: {
|
|
189
|
+
type: 'array',
|
|
190
|
+
description: 'Register IDs to scope the search (leave empty for org-wide)',
|
|
191
|
+
items: { type: 'string' }
|
|
192
|
+
},
|
|
193
|
+
filters: {
|
|
194
|
+
type: 'array',
|
|
195
|
+
description: 'Array of filter objects (top-level is implicit AND)',
|
|
196
|
+
items: {
|
|
197
|
+
type: 'object',
|
|
198
|
+
required: %w[operation params],
|
|
199
|
+
properties: {
|
|
200
|
+
operation: {
|
|
201
|
+
type: 'string',
|
|
202
|
+
description: 'Filter operation name (snake_case)'
|
|
203
|
+
},
|
|
204
|
+
params: {
|
|
205
|
+
type: 'object',
|
|
206
|
+
description: 'Operation parameters (key, value, ids, filters, gte, lte, etc.)'
|
|
207
|
+
}
|
|
208
|
+
}
|
|
209
|
+
}
|
|
210
|
+
},
|
|
211
|
+
sorters: {
|
|
212
|
+
type: 'array',
|
|
213
|
+
items: {
|
|
214
|
+
type: 'object',
|
|
215
|
+
required: %w[key direction],
|
|
216
|
+
properties: {
|
|
217
|
+
key: { type: 'string' },
|
|
218
|
+
direction: { type: 'string', enum: %w[asc desc] }
|
|
219
|
+
}
|
|
220
|
+
}
|
|
221
|
+
},
|
|
222
|
+
query: {
|
|
223
|
+
type: 'string',
|
|
224
|
+
description: 'Full-text search string (optional)'
|
|
225
|
+
}
|
|
226
|
+
}
|
|
227
|
+
}
|
|
228
|
+
}.freeze
|
|
229
|
+
end
|
|
230
|
+
end
|
|
231
|
+
end
|
|
232
|
+
end
|
|
233
|
+
end
|
|
234
|
+
end
|