eco-helpers 3.2.23 → 3.3.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 +92 -39
- data/lib/eco/api/common/session/base_session.rb +4 -0
- data/lib/eco/api/common/session/environment.rb +5 -0
- data/lib/eco/api/custom/cli.rb +3 -0
- data/lib/eco/api/session/config/api.rb +33 -14
- data/lib/eco/api/usecases/CLAUDE.md +78 -0
- data/lib/eco/api/usecases/graphql/CLAUDE.md +120 -0
- data/lib/eco/api/usecases/graphql/compat/ooze_redirect.rb +13 -2
- data/lib/eco/api/usecases/graphql/helpers/CLAUDE.md +79 -0
- data/lib/eco/api/usecases/graphql/helpers/access_logs/base/reader.rb +59 -0
- data/lib/eco/api/usecases/graphql/helpers/access_logs/base.rb +17 -0
- data/lib/eco/api/usecases/graphql/helpers/access_logs.rb +7 -0
- data/lib/eco/api/usecases/graphql/helpers/base/connection_reader.rb +70 -0
- data/lib/eco/api/usecases/graphql/helpers/base/graphql_env.rb +6 -2
- data/lib/eco/api/usecases/graphql/helpers/base.rb +1 -0
- data/lib/eco/api/usecases/graphql/helpers/contractors/base/manager_settings.rb +64 -0
- data/lib/eco/api/usecases/graphql/helpers/contractors/base.rb +2 -0
- data/lib/eco/api/usecases/graphql/helpers/dashboards/base/reader.rb +30 -0
- data/lib/eco/api/usecases/graphql/helpers/dashboards/base.rb +20 -0
- data/lib/eco/api/usecases/graphql/helpers/dashboards.rb +7 -0
- data/lib/eco/api/usecases/graphql/helpers/pages/activities.rb +51 -0
- data/lib/eco/api/usecases/graphql/helpers/pages.rb +2 -1
- data/lib/eco/api/usecases/graphql/helpers.rb +2 -0
- data/lib/eco/api/usecases/graphql/samples/CLAUDE.md +76 -0
- data/lib/eco/api/usecases/graphql/samples/contractors/dsl.rb +16 -0
- data/lib/eco/api/usecases/graphql/samples/pages/CLAUDE.md +59 -0
- data/lib/eco/api/usecases/graphql/samples/pages/template/base.rb +46 -37
- data/lib/eco/api/usecases/graphql/samples/pages/template.rb +1 -1
- data/lib/eco/version.rb +1 -1
- metadata +22 -7
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
require_relative 'base/reader'
|
|
2
|
+
|
|
3
|
+
module Eco::API::UseCases::GraphQL::Helpers::AccessLogs
|
|
4
|
+
# System Access Logs helper mixin — NATIVE reader over `activityLogs`.
|
|
5
|
+
module Base
|
|
6
|
+
include Eco::API::UseCases::GraphQL::Helpers::Base
|
|
7
|
+
|
|
8
|
+
private
|
|
9
|
+
|
|
10
|
+
# Build a lazy reader over the org's system access logs (ActivityLogUnion).
|
|
11
|
+
# @see Reader#initialize for the supported filters.
|
|
12
|
+
# @return [Reader]
|
|
13
|
+
def access_logs(**filters)
|
|
14
|
+
Reader.new(graphql, **filters)
|
|
15
|
+
end
|
|
16
|
+
end
|
|
17
|
+
end
|
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
module Eco::API::UseCases::GraphQL::Helpers::Base
|
|
2
|
+
# Shared substrate for NATIVE GraphQL connection readers.
|
|
3
|
+
#
|
|
4
|
+
# The gem's `Logic::QueryConnection` is already `Enumerable` and paginates lazily over
|
|
5
|
+
# `first`/`after` using `pageInfo.endCursor`/`hasNextPage` (see its `#each`). This mixin wraps
|
|
6
|
+
# that machinery behind a small, uniform reader surface so every native reader (access logs,
|
|
7
|
+
# page activities, dashboards, ...) exposes the same `each` / `to_a` / `first(n)` behaviour and
|
|
8
|
+
# a consistent `page_size` without re-implementing cursor pagination.
|
|
9
|
+
#
|
|
10
|
+
# A concrete reader supplies a `#query` (a gem query object, e.g.
|
|
11
|
+
# `graphql.currentOrganization.activityLogs`) and the per-call filter/argument hash via
|
|
12
|
+
# `#reader_params`. Everything else (lazy iteration, batching, materialising) is inherited.
|
|
13
|
+
module ConnectionReader
|
|
14
|
+
include Enumerable
|
|
15
|
+
|
|
16
|
+
# Default number of nodes fetched per network round-trip.
|
|
17
|
+
DEFAULT_PAGE_SIZE = 100
|
|
18
|
+
|
|
19
|
+
# Iterate over every node across all pages (lazy — one network page at a time).
|
|
20
|
+
# @yieldparam node [Object] a gem read model (e.g. Model::ActivityLog / Model::Activity).
|
|
21
|
+
# @return [Enumerator] when no block is given.
|
|
22
|
+
def each(&block)
|
|
23
|
+
return to_enum(:each) unless block
|
|
24
|
+
|
|
25
|
+
connection_query.each(**each_params, &block)
|
|
26
|
+
end
|
|
27
|
+
|
|
28
|
+
# Materialise a bounded number of nodes without draining the whole connection.
|
|
29
|
+
# @param limit [Integer, nil] maximum nodes to return; nil = all pages.
|
|
30
|
+
# @return [Array]
|
|
31
|
+
def to_a(limit: nil)
|
|
32
|
+
return super() if limit.nil?
|
|
33
|
+
|
|
34
|
+
take(limit)
|
|
35
|
+
end
|
|
36
|
+
|
|
37
|
+
# @return [Integer] nodes fetched per page.
|
|
38
|
+
def page_size
|
|
39
|
+
@page_size ||= DEFAULT_PAGE_SIZE
|
|
40
|
+
end
|
|
41
|
+
|
|
42
|
+
# @param size [Integer]
|
|
43
|
+
def page_size=(size)
|
|
44
|
+
@page_size = Integer(size)
|
|
45
|
+
end
|
|
46
|
+
|
|
47
|
+
private
|
|
48
|
+
|
|
49
|
+
# The gem query object to iterate (must respond to `#each(**kargs)` — i.e. a
|
|
50
|
+
# `Logic::QueryConnection`). Concrete readers MUST override.
|
|
51
|
+
# @return [Ecoportal::API::GraphQL::Logic::QueryConnection]
|
|
52
|
+
def connection_query
|
|
53
|
+
raise NotImplementedError, "#{self.class} must implement #connection_query"
|
|
54
|
+
end
|
|
55
|
+
|
|
56
|
+
# Per-call arguments (filters + page id + ...) merged into every page request.
|
|
57
|
+
# Concrete readers override to add their own filters. `first` defaults to `page_size`.
|
|
58
|
+
# @return [Hash]
|
|
59
|
+
def reader_params
|
|
60
|
+
{}
|
|
61
|
+
end
|
|
62
|
+
|
|
63
|
+
# Final kargs handed to the gem's `QueryConnection#each` — reader_params with a
|
|
64
|
+
# default `first`, and nils stripped so unset filters are not sent.
|
|
65
|
+
# @return [Hash]
|
|
66
|
+
def each_params
|
|
67
|
+
{ first: page_size }.merge(reader_params).compact
|
|
68
|
+
end
|
|
69
|
+
end
|
|
70
|
+
end
|
|
@@ -6,8 +6,12 @@ module Eco::API::UseCases::GraphQL::Helpers::Base
|
|
|
6
6
|
private
|
|
7
7
|
|
|
8
8
|
def graphql
|
|
9
|
-
|
|
10
|
-
|
|
9
|
+
unless session.api?(version: :graphql)
|
|
10
|
+
missing = session.missing_api_params(version: :graphql)
|
|
11
|
+
msg = "The credentials or basic graphql config are missing for the active environment"
|
|
12
|
+
msg << " (missing params: #{missing.map {|param| ":#{param}"}.join(', ')})" if missing.any?
|
|
13
|
+
raise msg
|
|
14
|
+
end
|
|
11
15
|
|
|
12
16
|
@graphql ||= session.api(version: :graphql)
|
|
13
17
|
end
|
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
module Eco::API::UseCases::GraphQL::Helpers::Contractors
|
|
2
|
+
module Base
|
|
3
|
+
# NATIVE contractor **write** helper — `updateContractorManagerSettings`.
|
|
4
|
+
#
|
|
5
|
+
# Drives the gem's `Builder::ContractorEntity#update_manager_settings` to set the
|
|
6
|
+
# organisation's contractor-manager auto-approval settings and whether contractor admins
|
|
7
|
+
# may add other admins.
|
|
8
|
+
#
|
|
9
|
+
# Guards (aligned with the repo's write discipline):
|
|
10
|
+
# - **dry-run / simulate:** when `simulate?` (or `dry_run:` is passed), NO mutation is sent;
|
|
11
|
+
# the intended input is logged and returned so callers can inspect it.
|
|
12
|
+
# - **-no-email:** honoured — when email is suppressed (`options.dig(:workflow, :no_email)`
|
|
13
|
+
# or an explicit `no_email:`), the helper does not emit its own success notification. The
|
|
14
|
+
# server-side mutation itself sends no member email for this settings change.
|
|
15
|
+
module ManagerSettings
|
|
16
|
+
include Eco::API::UseCases::GraphQL::Helpers::Base
|
|
17
|
+
|
|
18
|
+
private
|
|
19
|
+
|
|
20
|
+
# Update the org's contractor manager settings.
|
|
21
|
+
# @param cm_auto_approvals_settings [Hash, nil] AutoApprovalsInput
|
|
22
|
+
# ({ enabled:, approvalConditions: }). Required by the schema for a real update.
|
|
23
|
+
# @param allow_contractor_admins_to_add_admins [Boolean, nil]
|
|
24
|
+
# @param dry_run [Boolean, nil] force simulate for this call (in addition to `simulate?`).
|
|
25
|
+
# @param no_email [Boolean, nil] suppress this helper's own notification for this call.
|
|
26
|
+
# @return [Hash] when simulated: the intended input hash. Otherwise: the mutation payload.
|
|
27
|
+
def update_contractor_manager_settings(
|
|
28
|
+
cm_auto_approvals_settings: nil,
|
|
29
|
+
allow_contractor_admins_to_add_admins: nil,
|
|
30
|
+
dry_run: nil,
|
|
31
|
+
no_email: nil
|
|
32
|
+
)
|
|
33
|
+
input = {}
|
|
34
|
+
input[:cmAutoApprovalsSettings] = cm_auto_approvals_settings unless cm_auto_approvals_settings.nil?
|
|
35
|
+
unless allow_contractor_admins_to_add_admins.nil?
|
|
36
|
+
input[:allowContractorAdminsToAddAdmins] =
|
|
37
|
+
allow_contractor_admins_to_add_admins
|
|
38
|
+
end
|
|
39
|
+
|
|
40
|
+
if dry_run || simulate?
|
|
41
|
+
log(:info) { "[dry-run] updateContractorManagerSettings input: #{input}" }
|
|
42
|
+
return input
|
|
43
|
+
end
|
|
44
|
+
|
|
45
|
+
graphql.contractorEntity.update_manager_settings(input: input).tap do
|
|
46
|
+
notify_manager_settings_updated(input) unless suppress_email?(no_email)
|
|
47
|
+
end
|
|
48
|
+
end
|
|
49
|
+
|
|
50
|
+
# @return [Boolean] whether this helper's own notification email is suppressed.
|
|
51
|
+
def suppress_email?(no_email)
|
|
52
|
+
return true if no_email
|
|
53
|
+
return true if respond_to?(:options, true) && options.dig(:workflow, :no_email)
|
|
54
|
+
|
|
55
|
+
false
|
|
56
|
+
end
|
|
57
|
+
|
|
58
|
+
# Hook for a success notification (kept minimal; overridable). Logs by default.
|
|
59
|
+
def notify_manager_settings_updated(input)
|
|
60
|
+
log(:info) { "Updated contractor manager settings: #{input}" }
|
|
61
|
+
end
|
|
62
|
+
end
|
|
63
|
+
end
|
|
64
|
+
end
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
module Eco::API::UseCases::GraphQL::Helpers::Dashboards
|
|
2
|
+
module Base
|
|
3
|
+
# NATIVE reader over `currentOrganization.dashboardSearch` (MinimalDashboardConnection).
|
|
4
|
+
# Lazily paginates and yields `Model::MinimalDashboard` records.
|
|
5
|
+
#
|
|
6
|
+
# Use via `Helpers::Dashboards::Base#dashboards`:
|
|
7
|
+
# dashboards(query: 'safety').each { |d| ... }
|
|
8
|
+
# dashboards.to_a
|
|
9
|
+
class Reader
|
|
10
|
+
include Eco::API::UseCases::GraphQL::Helpers::Base::ConnectionReader
|
|
11
|
+
|
|
12
|
+
# @param graphql [Ecoportal::API::GraphQL] the active gem client.
|
|
13
|
+
# @param search_conf [Hash, nil] a `Search` input hash ({ query:, filters:, sorters: }).
|
|
14
|
+
def initialize(graphql, search_conf: nil)
|
|
15
|
+
@graphql = graphql
|
|
16
|
+
@search_conf = search_conf
|
|
17
|
+
end
|
|
18
|
+
|
|
19
|
+
private
|
|
20
|
+
|
|
21
|
+
def connection_query
|
|
22
|
+
@graphql.currentOrganization.dashboardSearch
|
|
23
|
+
end
|
|
24
|
+
|
|
25
|
+
def reader_params
|
|
26
|
+
{ searchConf: @search_conf }
|
|
27
|
+
end
|
|
28
|
+
end
|
|
29
|
+
end
|
|
30
|
+
end
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
require_relative 'base/reader'
|
|
2
|
+
|
|
3
|
+
module Eco::API::UseCases::GraphQL::Helpers::Dashboards
|
|
4
|
+
# Dashboards helper mixin — NATIVE reader over `dashboardSearch`.
|
|
5
|
+
module Base
|
|
6
|
+
include Eco::API::UseCases::GraphQL::Helpers::Base
|
|
7
|
+
|
|
8
|
+
private
|
|
9
|
+
|
|
10
|
+
# Build a lazy reader over the org's dashboards (MinimalDashboardConnection).
|
|
11
|
+
# @param query [String, nil] free-text search shorthand (→ search_conf { query: }).
|
|
12
|
+
# @param search_conf [Hash, nil] full Search input (takes precedence over `query`).
|
|
13
|
+
# @return [Reader]
|
|
14
|
+
def dashboards(query: nil, search_conf: nil)
|
|
15
|
+
conf = search_conf
|
|
16
|
+
conf ||= { query: query } if query
|
|
17
|
+
Reader.new(graphql, search_conf: conf)
|
|
18
|
+
end
|
|
19
|
+
end
|
|
20
|
+
end
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
module Eco::API::UseCases::GraphQL::Helpers::Pages
|
|
2
|
+
# NATIVE reader over `page(id:).activities` (the ActivityInterface behind a page's history /
|
|
3
|
+
# changelog feed). Lazily paginates and yields `Model::Activity` records.
|
|
4
|
+
#
|
|
5
|
+
# Use via `Helpers::Pages::Activities#page_activities`:
|
|
6
|
+
# page_activities(page_id).each { |a| ... }
|
|
7
|
+
# page_activities(page_id, sorters: [{ key: 'updated_at', direction: 'desc' }]).to_a(limit: 50)
|
|
8
|
+
module Activities
|
|
9
|
+
# Lazy activity-feed reader for a single page.
|
|
10
|
+
class Reader
|
|
11
|
+
include Eco::API::UseCases::GraphQL::Helpers::Base::ConnectionReader
|
|
12
|
+
|
|
13
|
+
# @param graphql [Ecoportal::API::GraphQL] the active gem client.
|
|
14
|
+
# @param page_id [String] the page id whose activities to read.
|
|
15
|
+
# @param search_conf [Hash, nil] a `Search` input hash (typically `{ sorters: [...] }`).
|
|
16
|
+
# Defaults to the web feature's ordering: newest updates first.
|
|
17
|
+
def initialize(graphql, page_id, search_conf: nil)
|
|
18
|
+
@graphql = graphql
|
|
19
|
+
@page_id = page_id
|
|
20
|
+
@search_conf = search_conf || DEFAULT_SEARCH_CONF
|
|
21
|
+
end
|
|
22
|
+
|
|
23
|
+
DEFAULT_SEARCH_CONF = { sorters: [{ direction: 'desc', key: 'updated_at' }] }.freeze
|
|
24
|
+
|
|
25
|
+
private
|
|
26
|
+
|
|
27
|
+
def connection_query
|
|
28
|
+
@graphql.currentOrganization.pageActivities
|
|
29
|
+
end
|
|
30
|
+
|
|
31
|
+
def reader_params
|
|
32
|
+
{ id: @page_id, searchConf: @search_conf }
|
|
33
|
+
end
|
|
34
|
+
end
|
|
35
|
+
|
|
36
|
+
include Eco::API::UseCases::GraphQL::Helpers::Base
|
|
37
|
+
|
|
38
|
+
private
|
|
39
|
+
|
|
40
|
+
# Build a lazy reader over a page's activity/history feed.
|
|
41
|
+
# @param page_id [String]
|
|
42
|
+
# @param sorters [Array<Hash>, nil] shorthand for `search_conf: { sorters: ... }`.
|
|
43
|
+
# @param search_conf [Hash, nil] full Search input (takes precedence over `sorters`).
|
|
44
|
+
# @return [Reader]
|
|
45
|
+
def page_activities(page_id, sorters: nil, search_conf: nil)
|
|
46
|
+
conf = search_conf
|
|
47
|
+
conf ||= { sorters: sorters } if sorters
|
|
48
|
+
Reader.new(graphql, page_id, search_conf: conf)
|
|
49
|
+
end
|
|
50
|
+
end
|
|
51
|
+
end
|
|
@@ -7,12 +7,13 @@ module Eco::API::UseCases::GraphQL::Helpers
|
|
|
7
7
|
# with duck-typing so they work against the GraphQL page/section/field models.
|
|
8
8
|
#
|
|
9
9
|
# This is Phase 1 of the ooze -> native GraphQL migration (build the shared substrate before
|
|
10
|
-
# any case). See
|
|
10
|
+
# any case). See ecoportal-api-graphql/.ai-assistance/projects/ooze-graphql-native-migration/.
|
|
11
11
|
module Pages
|
|
12
12
|
end
|
|
13
13
|
end
|
|
14
14
|
|
|
15
15
|
require_relative 'pages/shortcuts'
|
|
16
|
+
require_relative 'pages/activities'
|
|
16
17
|
require_relative 'pages/filters'
|
|
17
18
|
require_relative 'pages/ooze_handlers'
|
|
18
19
|
require_relative 'pages/rescuable'
|
|
@@ -0,0 +1,76 @@
|
|
|
1
|
+
# usecases/graphql/samples
|
|
2
|
+
|
|
3
|
+
Built-in GraphQL sample base classes shipped with the gem.
|
|
4
|
+
These are abstract/semi-abstract classes that org scripts inherit from.
|
|
5
|
+
Concrete, CLI-integrated cases go in `usecases/default/` instead.
|
|
6
|
+
|
|
7
|
+
---
|
|
8
|
+
|
|
9
|
+
## Hierarchy convention
|
|
10
|
+
|
|
11
|
+
Each domain follows:
|
|
12
|
+
```
|
|
13
|
+
samples/<domain>.rb ← namespace loader (may also BE the base class)
|
|
14
|
+
samples/<domain>/
|
|
15
|
+
<level>/
|
|
16
|
+
dsl.rb ← DSL concern — include in base, available to subclasses
|
|
17
|
+
base.rb ← Base class (inherits from GraphQL::Base or parent level)
|
|
18
|
+
<functional_level>.rb ← Optional: opinionated subclass, inherit directly
|
|
19
|
+
<functional_level>/
|
|
20
|
+
dsl.rb ← Further DSL for that functional level
|
|
21
|
+
```
|
|
22
|
+
|
|
23
|
+
DSLs are always **concerns (modules)** to include — never classes.
|
|
24
|
+
Bases are **classes** with the scaffolding logic.
|
|
25
|
+
Functional levels add opinionated defaults on top of base.
|
|
26
|
+
|
|
27
|
+
---
|
|
28
|
+
|
|
29
|
+
## Contents
|
|
30
|
+
|
|
31
|
+
| File | Class | Purpose |
|
|
32
|
+
|------|-------|---------|
|
|
33
|
+
| `samples/location.rb` | `Samples::Location` | Location structure management |
|
|
34
|
+
| `samples/location/command.rb` | `Samples::Location::Command` | Apply location tree commands |
|
|
35
|
+
| `samples/location/service.rb` | `Samples::Location::Service` | Tree diffing and conversion service |
|
|
36
|
+
| `samples/contractors.rb` | `Samples::Contractors` | Contractor entity base case |
|
|
37
|
+
| `samples/contractors/dsl.rb` | `Contractors::DSL` | Contractor helper mixin |
|
|
38
|
+
| `samples/pages.rb` | `Samples::Pages` (namespace) | Page processing cases loader |
|
|
39
|
+
| `samples/pages/page/dsl.rb` | `Pages::Page::DSL` | SearchConf helpers mixin |
|
|
40
|
+
| `samples/pages/page/base.rb` | `Pages::Page::Base` | Register-scoped page iteration |
|
|
41
|
+
| `samples/pages/org_page/dsl.rb` | `Pages::OrgPage::DSL` | Org-page DSL (extends Page::DSL) |
|
|
42
|
+
| `samples/pages/org_page/base.rb` | `Pages::OrgPage::Base` | Org-wide page iteration |
|
|
43
|
+
|
|
44
|
+
---
|
|
45
|
+
|
|
46
|
+
## Difference: samples vs org-specific cases vs default
|
|
47
|
+
|
|
48
|
+
| Layer | Location | Purpose |
|
|
49
|
+
|---|---|---|
|
|
50
|
+
| **samples** (here) | `eco-helpers/lib/.../graphql/samples/` | Abstract base classes — org scripts inherit |
|
|
51
|
+
| **default** | `eco-helpers/lib/.../usecases/default/` | Concrete CLI-integrated cases for ALL orgs |
|
|
52
|
+
| **org-specific** | `multi_org_api/{org}/config/graphql_cases/` | Org-specific implementations |
|
|
53
|
+
|
|
54
|
+
Org scripts inherit from `samples/`, optionally via `default/` as an intermediate layer.
|
|
55
|
+
|
|
56
|
+
---
|
|
57
|
+
|
|
58
|
+
## Adding a new built-in sample
|
|
59
|
+
|
|
60
|
+
1. Create the case file in `samples/`:
|
|
61
|
+
```ruby
|
|
62
|
+
# lib/eco/api/usecases/graphql/samples/my_domain.rb
|
|
63
|
+
class Eco::API::UseCases::GraphQL::Samples::MyDomain < Eco::API::UseCases::GraphQL::Base
|
|
64
|
+
name 'my-domain-case'
|
|
65
|
+
type :other
|
|
66
|
+
|
|
67
|
+
def process
|
|
68
|
+
# ...
|
|
69
|
+
end
|
|
70
|
+
end
|
|
71
|
+
```
|
|
72
|
+
|
|
73
|
+
2. Add `require_relative 'samples/my_domain'` to `samples.rb`.
|
|
74
|
+
|
|
75
|
+
If the case is page-centric, inherit from `PageCase` instead of `Base` to get
|
|
76
|
+
pagination, KPI tracking, and `update_page` for free.
|
|
@@ -1,5 +1,21 @@
|
|
|
1
1
|
module Eco::API::UseCases::GraphQL::Samples
|
|
2
2
|
module Contractors::DSL
|
|
3
3
|
include Eco::API::UseCases::GraphQL::Helpers::Contractors::Base
|
|
4
|
+
|
|
5
|
+
private
|
|
6
|
+
|
|
7
|
+
# Sample command: update the org's contractor manager settings (auto-approvals +
|
|
8
|
+
# whether contractor admins may add other admins). Delegates to the guarded helper
|
|
9
|
+
# `#update_contractor_manager_settings` (dry-run/simulate + -no-email honoured).
|
|
10
|
+
#
|
|
11
|
+
# @param auto_approvals [Hash, nil] AutoApprovalsInput ({ enabled:, approvalConditions: }).
|
|
12
|
+
# @param allow_admins_add_admins [Boolean, nil]
|
|
13
|
+
# @return [Hash] the intended input when simulated, else the mutation payload.
|
|
14
|
+
def update_manager_settings(auto_approvals: nil, allow_admins_add_admins: nil)
|
|
15
|
+
update_contractor_manager_settings(
|
|
16
|
+
cm_auto_approvals_settings: auto_approvals,
|
|
17
|
+
allow_contractor_admins_to_add_admins: allow_admins_add_admins
|
|
18
|
+
)
|
|
19
|
+
end
|
|
4
20
|
end
|
|
5
21
|
end
|
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
# samples/pages
|
|
2
|
+
|
|
3
|
+
Base classes for GraphQL-native page processing use cases.
|
|
4
|
+
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
## Structure
|
|
8
|
+
|
|
9
|
+
```
|
|
10
|
+
pages/
|
|
11
|
+
page/
|
|
12
|
+
dsl.rb ← Page::DSL — SearchConf helpers mixin (sc, in_register, state_is, ...)
|
|
13
|
+
base.rb ← Page::Base — register-scoped page iteration + KPI scaffolding
|
|
14
|
+
org_page/
|
|
15
|
+
dsl.rb ← OrgPage::DSL — extends Page::DSL (org-wide helpers)
|
|
16
|
+
base.rb ← OrgPage::Base — org-wide iteration (no default register scope)
|
|
17
|
+
```
|
|
18
|
+
|
|
19
|
+
---
|
|
20
|
+
|
|
21
|
+
## Inheritance
|
|
22
|
+
|
|
23
|
+
```
|
|
24
|
+
GraphQL::Base
|
|
25
|
+
↓
|
|
26
|
+
Samples::Pages::Page::Base (register-scoped, inherits Page::DSL)
|
|
27
|
+
↓
|
|
28
|
+
Samples::Pages::OrgPage::Base (org-wide, overrides search_conf)
|
|
29
|
+
↓
|
|
30
|
+
your org subclass
|
|
31
|
+
```
|
|
32
|
+
|
|
33
|
+
---
|
|
34
|
+
|
|
35
|
+
## Page::Base — register-scoped scripts
|
|
36
|
+
|
|
37
|
+
Override `process_page(page)` and optionally `search_conf`.
|
|
38
|
+
Set `register_id` and `batch_size` on the class.
|
|
39
|
+
|
|
40
|
+
## OrgPage::Base — org-wide scripts
|
|
41
|
+
|
|
42
|
+
Same as Page::Base but `search_conf` starts empty.
|
|
43
|
+
Add your own filters via `super.filter(state_is(:active))` etc.
|
|
44
|
+
|
|
45
|
+
---
|
|
46
|
+
|
|
47
|
+
## Adding a functional level
|
|
48
|
+
|
|
49
|
+
If a common pattern emerges (e.g., "stage-submit scripts"), add:
|
|
50
|
+
|
|
51
|
+
```
|
|
52
|
+
pages/page/
|
|
53
|
+
stage_submitter.rb ← Page::StageSubmitter < Page::Base
|
|
54
|
+
stage_submitter/
|
|
55
|
+
dsl.rb ← StageSubmitter::DSL
|
|
56
|
+
```
|
|
57
|
+
|
|
58
|
+
Keep base.rb for the pure iteration scaffolding; put opinionated defaults in
|
|
59
|
+
the functional level so scripts can choose their entry point.
|
|
@@ -1,4 +1,11 @@
|
|
|
1
1
|
module Eco::API::UseCases::GraphQL::Samples::Pages
|
|
2
|
+
# NOTE: nested as `module Template` + `class Base` rather than the compact `class Template::Base`
|
|
3
|
+
# ON PURPOSE. The compact form leaves `Template` out of this file's lexical scope, so the bare
|
|
4
|
+
# `CommandEmitter` reference in #desired_commands resolved against Base and Pages only and raised
|
|
5
|
+
# NameError on every call -- the class could never run. Sibling files (command_emitter.rb,
|
|
6
|
+
# csv_build/builder.rb) all open the Template module properly, which is why their bare references
|
|
7
|
+
# to each other work. Keep this nesting.
|
|
8
|
+
#
|
|
2
9
|
# Build-from-scratch template (workflow) construction use case.
|
|
3
10
|
#
|
|
4
11
|
# A subclass declares the desired template structure in #declare(emitter) using the
|
|
@@ -17,54 +24,56 @@ module Eco::API::UseCases::GraphQL::Samples::Pages
|
|
|
17
24
|
# end
|
|
18
25
|
# end
|
|
19
26
|
# end
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
27
|
+
module Template
|
|
28
|
+
class Base < Eco::API::UseCases::GraphQL::Base
|
|
29
|
+
name 'graphql-template-base'
|
|
30
|
+
type :other
|
|
23
31
|
|
|
24
|
-
|
|
32
|
+
require_relative 'command_emitter'
|
|
25
33
|
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
34
|
+
def process
|
|
35
|
+
commands = desired_commands
|
|
36
|
+
if simulate?
|
|
37
|
+
log(:info) { preview_message(commands) }
|
|
38
|
+
return nil
|
|
39
|
+
end
|
|
40
|
+
apply(commands)
|
|
31
41
|
end
|
|
32
|
-
apply(commands)
|
|
33
|
-
end
|
|
34
42
|
|
|
35
|
-
|
|
43
|
+
# == Subclass override point ================================================
|
|
36
44
|
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
45
|
+
# Declare the desired template structure onto the given CommandEmitter.
|
|
46
|
+
def declare(_emitter)
|
|
47
|
+
raise NotImplementedError, "Implement #declare(emitter) in #{self.class}"
|
|
48
|
+
end
|
|
41
49
|
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
50
|
+
# The ordered command batch this template would apply. Pure — no client needed.
|
|
51
|
+
def desired_commands
|
|
52
|
+
emitter = CommandEmitter.new
|
|
53
|
+
declare(emitter)
|
|
54
|
+
emitter.commands
|
|
55
|
+
end
|
|
48
56
|
|
|
49
|
-
|
|
57
|
+
protected
|
|
50
58
|
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
59
|
+
# Persist a fresh template from the command batch. Override to #update an existing one.
|
|
60
|
+
def apply(commands)
|
|
61
|
+
graphql.template.create(commands: commands)
|
|
62
|
+
end
|
|
55
63
|
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
64
|
+
# Update an existing template model with the command batch.
|
|
65
|
+
def apply_update(model, commands)
|
|
66
|
+
graphql.template.update(model, commands: commands)
|
|
67
|
+
end
|
|
60
68
|
|
|
61
|
-
|
|
69
|
+
private
|
|
62
70
|
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
71
|
+
def preview_message(commands)
|
|
72
|
+
[
|
|
73
|
+
"Simulate — would apply #{commands.size} workflow command(s):",
|
|
74
|
+
*commands.map { |c| " * #{c.keys.first}: #{c.values.first.inspect}" }
|
|
75
|
+
].join("\n")
|
|
76
|
+
end
|
|
68
77
|
end
|
|
69
78
|
end
|
|
70
79
|
end
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
module Eco::API::UseCases::GraphQL::Samples::Pages
|
|
2
2
|
# Template (workflow) build-from-scratch + (later) diff-and-update samples.
|
|
3
|
-
# See
|
|
3
|
+
# See ecoportal-api-graphql/.ai-assistance/projects/template-maintenance/.
|
|
4
4
|
module Template
|
|
5
5
|
end
|
|
6
6
|
end
|
data/lib/eco/version.rb
CHANGED