diff --git a/lib/trailblazer/workflow/collaboration.rb b/lib/trailblazer/workflow/collaboration.rb index 6a98d20..32a13b5 100644 --- a/lib/trailblazer/workflow/collaboration.rb +++ b/lib/trailblazer/workflow/collaboration.rb @@ -2,10 +2,12 @@ module Trailblazer module Workflow # User-friendly builder. def self.Collaboration(json_file:, lanes:, state_guards: nil) - ctx = Collaboration.structure_from_filename(json_file) + _, (ctx, _) = Collaboration::Structure.invoke([{json_filename: json_file}, {}]) + + lane_options_from_structure = ctx[:lane_hints] lanes_options = lanes.collect do |json_id, user_options| - lane_options = normalize_lane_options(**user_options) + lane_options = normalize_lane_options(**lane_options_from_structure[json_id]) activity = build_lane_for(**ctx, **user_options, json_id: json_id) @@ -27,8 +29,8 @@ def self.Collaboration(json_file:, lanes:, state_guards: nil) end # DISCUSS: use Activity here? - def self.normalize_lane_options(label:, icon:, **) - {label: label, icon: icon} + def self.normalize_lane_options(label:, icon:, name:, **) + {label: label, icon: icon, name: name} end def self.build_lane_for(intermediates:, implementation:, json_id:, **) @@ -41,10 +43,32 @@ def self.build_lane_for(intermediates:, implementation:, json_id:, **) end class Collaboration - def self.structure_from_filename(json_file) - json_from_pro = File.read(json_file) - signal, (ctx, _) = Trailblazer::Workflow::Generate.invoke([{json_document: json_from_pro}, {}]) - ctx + class Structure < Trailblazer::Activity::Railway + step :read_file + step Subprocess(Trailblazer::Workflow::Parse) + step :compute_lane_hints + + def read_file(ctx, json_filename:, **) + ctx[:json_document] = File.read(json_filename) + end + + def compute_lane_hints(ctx, structure:, **) + lane_hints = structure.lanes.collect do |lane| + icon, label, name = lane.id.split(".") # TODO: validate/default. + + + hints = { + json_id: lane.id, + label: label, + icon: icon, + name: name + } + + [lane.id, hints] + end.to_h + + ctx[:lane_hints] = lane_hints + end end class Schema diff --git a/lib/trailblazer/workflow/discovery.rb b/lib/trailblazer/workflow/discovery.rb index 6360b0a..ea12f81 100644 --- a/lib/trailblazer/workflow/discovery.rb +++ b/lib/trailblazer/workflow/discovery.rb @@ -14,8 +14,8 @@ def stub_task(lane_label, task_label) stub_task = Trailblazer::Activity::Testing.def_tasks(stub_task_name).method(stub_task_name) end - def call(json_filename:, lane_hints:) - ctx = Trailblazer::Workflow::Collaboration.structure_from_filename(json_filename) + def call(json_filename:) + _, (ctx, _) = Collaboration::Structure.invoke([{json_filename: json_filename}, {}]) stubbed_lanes = ctx[:intermediates].collect do |json_id, intermediate| lane_task_2_wiring = intermediate.wiring.find_all { |task_ref, _| task_ref.data[:type] == :task } @@ -31,7 +31,7 @@ def call(json_filename:, lane_hints:) [ json_id, - {label: rand, icon: rand, implementation: stubbed_tasks}.merge(lane_hints[json_id]) + {implementation: stubbed_tasks} ] end.to_h @@ -44,7 +44,7 @@ def call(json_filename:, lane_hints:) # Find all possible configurations for a {collaboration} by replacing # its tasks with mocks, and run through all possible paths. # FIXME: initial_lane_positions defaulting is not tested. - def call(json_filename:, start_lane:, dsl_options_for_run_multiple_times: {}, lane_hints: {}) + def call(json_filename:, start_lane:, dsl_options_for_run_multiple_times: {}) # State discovery: # The idea is that we collect suspend events and follow up on all their resumes (catch) events. # We can't see into {Collaboration.call}, meaning we can really only collect public entry points, @@ -58,7 +58,7 @@ def call(json_filename:, start_lane:, dsl_options_for_run_multiple_times: {}, la # imply we start from a public resume and discover the path? # we could save work on {run_multiple_times} with this. - collaboration = Stub.(json_filename: json_filename, lane_hints: lane_hints) + collaboration = Stub.(json_filename: json_filename) initial_lane_positions = Collaboration::Synchronous.initial_lane_positions(collaboration.to_h[:lanes]) initial_lane_positions = Collaboration::Positions.new(initial_lane_positions.collect { |activity, task| Trailblazer::Workflow::Collaboration::Position.new(activity, task) }) # FIXME: initial_lane_positions should return {Collaboration::Positions} diff --git a/test/test_helper.rb b/test/test_helper.rb index 72555b1..4e68994 100644 --- a/test/test_helper.rb +++ b/test/test_helper.rb @@ -36,11 +36,9 @@ def build_schema() implementing_editor = Trailblazer::Activity::Testing.def_steps(:Notify, :Reject, :Approve) schema = Trailblazer::Workflow.Collaboration( - json_file: "test/fixtures/v1/posting-v10.json", + json_file: "test/fixtures/v1/posting-v11.json", lanes: { - "article moderation" => { - label: "lifecycle", - icon: "⛾", + "⛾.lifecycle.posting" => { implementation: { "Create" => Trailblazer::Activity::Railway.Subprocess(Create), "Update" => implementing.method(:update), @@ -53,9 +51,7 @@ def build_schema() "Delete" => implementing.method(:delete), } }, - " author workflow" => { - label: "UI", - icon: "☝", + "☝.UI.blogger" => { implementation: { "Create form" => implementing_ui.method(:create_form), "Create" => implementing_ui.method(:ui_create), @@ -75,9 +71,7 @@ def build_schema() } }, - "reviewer"=> { - label: "editor", - icon: "☑", + "☑.editor.reviewer" => { implementation: { "Notify" => implementing_editor.method(:Notify), "Reject" => implementing_editor.method(:Reject), @@ -98,7 +92,7 @@ module DiscoveredStates def states states, stub_schema = Trailblazer::Workflow::Discovery.( json_filename: "test/fixtures/v1/posting-v10.json", - start_lane: " author workflow", + start_lane: "UI", # TODO: allow translating the original "id" (?) to the stubbed. dsl_options_for_run_multiple_times: { @@ -109,18 +103,11 @@ def states # }, config_payload: {outcome: :failure}}, # Click [UI Create] again, with invalid data. - [" author workflow", "Create"] => {ctx_merge: {:"article moderation:Create" => Trailblazer::Activity::Left}, config_payload: {outcome: :failure}}, + ["UI", "Create"] => {ctx_merge: {:"article moderation:Create" => Trailblazer::Activity::Left}, config_payload: {outcome: :failure}}, # Click [UI Update] again, with invalid data. - [" author workflow", "Update"] => {ctx_merge: {:"article moderation:Update" => Trailblazer::Activity::Left}, config_payload: {outcome: :failure}}, - [" author workflow", "Revise"] => {ctx_merge: {:"article moderation:Revise" => Trailblazer::Activity::Left}, config_payload: {outcome: :failure}}, + ["UI", "Update"] => {ctx_merge: {:"article moderation:Update" => Trailblazer::Activity::Left}, config_payload: {outcome: :failure}}, + ["UI", "Revise"] => {ctx_merge: {:"article moderation:Revise" => Trailblazer::Activity::Left}, config_payload: {outcome: :failure}}, }, - - # DISCUSS: compute this automatically/from diagram? - lane_hints: { - " author workflow" => {label: "UI", icon: "☝"}, - "article moderation" => {label: "lifecycle", icon: "⛾"}, - "reviewer" => {label: "editor", icon: "☑"}, - } ) return states, stub_schema, stub_schema.to_h[:lanes]