workflowable 1.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/LICENSE +202 -0
- data/README.md +23 -0
- data/Rakefile +39 -0
- data/app/assets/images/workflowable/select2-spinner.gif +0 -0
- data/app/assets/images/workflowable/select2.png +0 -0
- data/app/assets/images/workflowable/select2x2.png +0 -0
- data/app/assets/javascripts/workflowable/application.js +118 -0
- data/app/assets/javascripts/workflowable/d3.min.js +5 -0
- data/app/assets/javascripts/workflowable/dagre-min.js +2 -0
- data/app/assets/javascripts/workflowable/foundation/fastclick.js +9 -0
- data/app/assets/javascripts/workflowable/foundation/foundation.min.js +10 -0
- data/app/assets/javascripts/workflowable/foundation/modernizr.js +8 -0
- data/app/assets/javascripts/workflowable/foundation/placeholder.js +2 -0
- data/app/assets/javascripts/workflowable/select2.min.js +22 -0
- data/app/assets/javascripts/workflowable/workflow.js +2 -0
- data/app/assets/stylesheets/workflowable/application.css +26 -0
- data/app/assets/stylesheets/workflowable/dagre-d3.css +19 -0
- data/app/assets/stylesheets/workflowable/foundation/foundation.min.css +1 -0
- data/app/assets/stylesheets/workflowable/foundation/normalize.css +423 -0
- data/app/assets/stylesheets/workflowable/select2.css +646 -0
- data/app/assets/stylesheets/workflowable/workflow.css +4 -0
- data/app/controllers/workflowable/actions_controller.rb +35 -0
- data/app/controllers/workflowable/application_controller.rb +18 -0
- data/app/controllers/workflowable/workflows_controller.rb +137 -0
- data/app/helpers/workflowable/application_helper.rb +19 -0
- data/app/helpers/workflowable/workflow_helper.rb +19 -0
- data/app/models/workflowable/action.rb +113 -0
- data/app/models/workflowable/stage.rb +104 -0
- data/app/models/workflowable/stage_action.rb +24 -0
- data/app/models/workflowable/stage_next_step.rb +21 -0
- data/app/models/workflowable/workflow.rb +57 -0
- data/app/models/workflowable/workflow_action.rb +23 -0
- data/app/views/layouts/workflowable/application.html.erb +24 -0
- data/app/views/shared/actions/_details.html.erb +30 -0
- data/app/views/shared/actions/_fields.html.erb +26 -0
- data/app/views/workflowable/actions/_options.html.erb +39 -0
- data/app/views/workflowable/actions/options.js.erb +2 -0
- data/app/views/workflowable/workflows/_form.html.erb +57 -0
- data/app/views/workflowable/workflows/configure_stages.html.erb +34 -0
- data/app/views/workflowable/workflows/edit.html.erb +2 -0
- data/app/views/workflowable/workflows/index.html.erb +16 -0
- data/app/views/workflowable/workflows/new.html.erb +2 -0
- data/app/views/workflowable/workflows/show.html.erb +49 -0
- data/app/views/workflowable/workflows/stages.json.jbuilder +8 -0
- data/config/routes.rb +34 -0
- data/db/migrate/20140406195941_create_workflowable_workflows.rb +25 -0
- data/db/migrate/20140407170846_create_workflowable_stages.rb +25 -0
- data/db/migrate/20140407184821_rename_workflow_initial_stage_to_initial_stage_id.rb +20 -0
- data/db/migrate/20140407191620_create_workflowable_stage_next_steps.rb +25 -0
- data/db/migrate/20140407193057_create_workflowable_stage_actions.rb +26 -0
- data/db/migrate/20140407194247_create_workflowable_actions.rb +26 -0
- data/db/migrate/20140408164900_create_workflowable_workflow_actions.rb +25 -0
- data/db/migrate/20140708173311_add_order_to_action.rb +20 -0
- data/db/migrate/20140818062426_add_position_to_stage_action.rb +20 -0
- data/lib/tasks/workflowable_tasks.rake +4 -0
- data/lib/workflowable.rb +26 -0
- data/lib/workflowable/actions/action.rb +76 -0
- data/lib/workflowable/engine.rb +47 -0
- data/lib/workflowable/model_additions.rb +152 -0
- data/lib/workflowable/railtie.rb +25 -0
- data/lib/workflowable/version.rb +18 -0
- metadata +301 -0
@@ -0,0 +1,24 @@
|
|
1
|
+
# Copyright 2014 Netflix, Inc.
|
2
|
+
#
|
3
|
+
# Licensed under the Apache License, Version 2.0 (the "License");
|
4
|
+
# you may not use this file except in compliance with the License.
|
5
|
+
# You may obtain a copy of the License at
|
6
|
+
#
|
7
|
+
# http://www.apache.org/licenses/LICENSE-2.0
|
8
|
+
#
|
9
|
+
# Unless required by applicable law or agreed to in writing, software
|
10
|
+
# distributed under the License is distributed on an "AS IS" BASIS,
|
11
|
+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
12
|
+
# See the License for the specific language governing permissions and
|
13
|
+
# limitations under the License.
|
14
|
+
|
15
|
+
|
16
|
+
module Workflowable
|
17
|
+
class StageAction < ActiveRecord::Base
|
18
|
+
belongs_to :stage
|
19
|
+
belongs_to :action
|
20
|
+
|
21
|
+
delegate :position, to: :action
|
22
|
+
|
23
|
+
end
|
24
|
+
end
|
@@ -0,0 +1,21 @@
|
|
1
|
+
# Copyright 2014 Netflix, Inc.
|
2
|
+
#
|
3
|
+
# Licensed under the Apache License, Version 2.0 (the "License");
|
4
|
+
# you may not use this file except in compliance with the License.
|
5
|
+
# You may obtain a copy of the License at
|
6
|
+
#
|
7
|
+
# http://www.apache.org/licenses/LICENSE-2.0
|
8
|
+
#
|
9
|
+
# Unless required by applicable law or agreed to in writing, software
|
10
|
+
# distributed under the License is distributed on an "AS IS" BASIS,
|
11
|
+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
12
|
+
# See the License for the specific language governing permissions and
|
13
|
+
# limitations under the License.
|
14
|
+
|
15
|
+
|
16
|
+
module Workflowable
|
17
|
+
class StageNextStep < ActiveRecord::Base
|
18
|
+
belongs_to :current_stage, :class_name=>'Stage'
|
19
|
+
belongs_to :next_stage, :class_name=>'Stage'
|
20
|
+
end
|
21
|
+
end
|
@@ -0,0 +1,57 @@
|
|
1
|
+
# Copyright 2014 Netflix, Inc.
|
2
|
+
#
|
3
|
+
# Licensed under the Apache License, Version 2.0 (the "License");
|
4
|
+
# you may not use this file except in compliance with the License.
|
5
|
+
# You may obtain a copy of the License at
|
6
|
+
#
|
7
|
+
# http://www.apache.org/licenses/LICENSE-2.0
|
8
|
+
#
|
9
|
+
# Unless required by applicable law or agreed to in writing, software
|
10
|
+
# distributed under the License is distributed on an "AS IS" BASIS,
|
11
|
+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
12
|
+
# See the License for the specific language governing permissions and
|
13
|
+
# limitations under the License.
|
14
|
+
|
15
|
+
|
16
|
+
module Workflowable
|
17
|
+
class Workflow < ActiveRecord::Base
|
18
|
+
has_many :stages, :inverse_of=>:workflow
|
19
|
+
belongs_to :initial_stage, :class_name=>Stage
|
20
|
+
has_many :workflow_actions, -> { order("position ASC") }
|
21
|
+
has_many :actions, :through=>:workflow_actions
|
22
|
+
accepts_nested_attributes_for :stages, :allow_destroy => true
|
23
|
+
accepts_nested_attributes_for :actions, :allow_destroy => true
|
24
|
+
|
25
|
+
|
26
|
+
|
27
|
+
validates :name, :presence=>true
|
28
|
+
validates :name, :uniqueness=>true
|
29
|
+
|
30
|
+
|
31
|
+
|
32
|
+
def run_workflow_actions(options={}, object, current_stage, next_stage, user)
|
33
|
+
actions.each do |action|
|
34
|
+
action.run(options.try(:[],action.name), self, object, current_stage, next_stage, user)
|
35
|
+
end
|
36
|
+
end
|
37
|
+
|
38
|
+
def workflow_action_options(options={}, object, current_stage, next_stage, user)
|
39
|
+
options ||= {}
|
40
|
+
workflow_action_options = {}
|
41
|
+
actions.each do |action|
|
42
|
+
workflow_action_options[action.name] = action.available_options(options.try(:[],action.name) || {}, self, object, current_stage, next_stage, user)
|
43
|
+
end
|
44
|
+
workflow_action_options
|
45
|
+
end
|
46
|
+
|
47
|
+
def validate_action_options(options={}, object, current_stage, next_stage, user)
|
48
|
+
options ||= {}
|
49
|
+
action_errors = {}
|
50
|
+
actions.each do |action|
|
51
|
+
errors = action.validate_options(options[action.name] || {}, self, object, current_stage, next_stage, user)
|
52
|
+
action_errors[action.name] = errors if errors.present?
|
53
|
+
end
|
54
|
+
action_errors
|
55
|
+
end
|
56
|
+
end
|
57
|
+
end
|
@@ -0,0 +1,23 @@
|
|
1
|
+
# Copyright 2014 Netflix, Inc.
|
2
|
+
#
|
3
|
+
# Licensed under the Apache License, Version 2.0 (the "License");
|
4
|
+
# you may not use this file except in compliance with the License.
|
5
|
+
# You may obtain a copy of the License at
|
6
|
+
#
|
7
|
+
# http://www.apache.org/licenses/LICENSE-2.0
|
8
|
+
#
|
9
|
+
# Unless required by applicable law or agreed to in writing, software
|
10
|
+
# distributed under the License is distributed on an "AS IS" BASIS,
|
11
|
+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
12
|
+
# See the License for the specific language governing permissions and
|
13
|
+
# limitations under the License.
|
14
|
+
|
15
|
+
|
16
|
+
module Workflowable
|
17
|
+
class WorkflowAction < ActiveRecord::Base
|
18
|
+
belongs_to :workflow
|
19
|
+
belongs_to :action
|
20
|
+
|
21
|
+
|
22
|
+
end
|
23
|
+
end
|
@@ -0,0 +1,24 @@
|
|
1
|
+
<!DOCTYPE html>
|
2
|
+
<html>
|
3
|
+
<head>
|
4
|
+
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
5
|
+
<title>Workflowable</title>
|
6
|
+
<%= stylesheet_link_tag "workflowable/application", media: "all" %>
|
7
|
+
<%= javascript_include_tag "workflowable/application" %>
|
8
|
+
<%= csrf_meta_tags %>
|
9
|
+
</head>
|
10
|
+
<body>
|
11
|
+
<nav class="top-bar hide-for-small" data-topbar="">
|
12
|
+
<ul class="title-area">
|
13
|
+
<li class="name">
|
14
|
+
<h1><%= link_to "Workflowable", workflows_path %></h1>
|
15
|
+
</li>
|
16
|
+
</ul>
|
17
|
+
</nav>
|
18
|
+
<div class="row">
|
19
|
+
<div class="large-12 columns">
|
20
|
+
<%= yield %>
|
21
|
+
</div>
|
22
|
+
</div>
|
23
|
+
</body>
|
24
|
+
</html>
|
@@ -0,0 +1,30 @@
|
|
1
|
+
<% if actions.count == 0 %>
|
2
|
+
<b>No actions defined</b>
|
3
|
+
<% else %>
|
4
|
+
<% actions.each do |action| %>
|
5
|
+
<h6><b><%= action.name %></b>
|
6
|
+
(<%= action.action_plugin %>)</h6>
|
7
|
+
<table>
|
8
|
+
<thead>
|
9
|
+
<tr>
|
10
|
+
<th>Option</th>
|
11
|
+
<th>Value Specified</th>
|
12
|
+
<th>Default Value</th>
|
13
|
+
</tr>
|
14
|
+
</thead>
|
15
|
+
<tbody>
|
16
|
+
<% if action.options.present? %>
|
17
|
+
<% action.options.each do |k,v| %>
|
18
|
+
<tr>
|
19
|
+
<td><%= k %></td>
|
20
|
+
<td><%= v.try(:[],:value) %></td>
|
21
|
+
<td><%= v.try(:[],:default) %></td>
|
22
|
+
</tr>
|
23
|
+
<% end %>
|
24
|
+
<% else %>
|
25
|
+
<tr ><td colspan="3">No options defined</td></tr>
|
26
|
+
<% end %>
|
27
|
+
</tbody>
|
28
|
+
</table>
|
29
|
+
<% end %>
|
30
|
+
<% end %>
|
@@ -0,0 +1,26 @@
|
|
1
|
+
<%= f.fields_for association do |action_form| %>
|
2
|
+
<fieldset>
|
3
|
+
<legend><%= label.humanize %>
|
4
|
+
details -
|
5
|
+
<%= action_form.link_to_remove "Remove" %></legend>
|
6
|
+
<div class="field">
|
7
|
+
<%= action_form.label :action_name %>
|
8
|
+
<%= action_form.text_field :name %>
|
9
|
+
<%= action_form.label :position %>
|
10
|
+
<%= action_form.text_field :position %>
|
11
|
+
</div>
|
12
|
+
<div class="field">
|
13
|
+
<%= action_form.label :action %>
|
14
|
+
<%= action_form.collection_select :action_plugin, Workflowable::Actions.constants, :to_s, :to_s, {include_blank: true}, {class: "action_plugin_select"} %>
|
15
|
+
</div>
|
16
|
+
<div class="action_options_fields" data-url="<%= options_actions_url %>" data-context="<%= action_form.object_name %>">
|
17
|
+
<% available_options = action_form.object.available_options(action_form.object.options) %>
|
18
|
+
<% if available_options %>
|
19
|
+
<%= render :partial=>"workflowable/actions/options", :locals => {:options=>available_options , context: action_form.object_name } %>
|
20
|
+
<% end %>
|
21
|
+
</div>
|
22
|
+
<br/>
|
23
|
+
</fieldset>
|
24
|
+
<br/>
|
25
|
+
<% end %>
|
26
|
+
<p><%= f.link_to_add "Add #{label}", association %></p>
|
@@ -0,0 +1,39 @@
|
|
1
|
+
<%= fields_for "#{context}[options]", OpenStruct.new({}) do |options_form| %>
|
2
|
+
<% options.each do |key, value| %>
|
3
|
+
<div class="field">
|
4
|
+
<div class="row">
|
5
|
+
<div class="medium-5 columns">
|
6
|
+
<%= label_tag do %>
|
7
|
+
Specify Value:
|
8
|
+
<%= value.try(:[],:name) || key.to_s %>
|
9
|
+
<%= "(required)" if value[:required] == true %>
|
10
|
+
<% end %>
|
11
|
+
<% if value[:type] == :choice %>
|
12
|
+
<%= options_form.select "#{key}][value", value[:choices].collect{|v| [v[:name],v.to_json]},{ include_blank: true, selected: value[:value].to_json} %>
|
13
|
+
<% elsif value[:type] == :boolean %>
|
14
|
+
<%= options_form.check_box "#{key}][value", :checked=>value[:value] == "1" %>
|
15
|
+
<% else %>
|
16
|
+
<%= options_form.text_field "#{key}][value", :value=>value[:value] %>
|
17
|
+
<% end %>
|
18
|
+
</div>
|
19
|
+
<div class="medium-1 columns">
|
20
|
+
<br/>
|
21
|
+
<b>OR</b>
|
22
|
+
</div>
|
23
|
+
<div class="medium-6 columns">
|
24
|
+
<%= label_tag do %>
|
25
|
+
Default Value:
|
26
|
+
<%= value.try(:[],:name) || key.to_s %>
|
27
|
+
<% end %>
|
28
|
+
<% if value[:type] == :choice %>
|
29
|
+
<%= options_form.select "#{key}][default", value[:choices].collect{|v| [v[:name],v.to_json]},{ include_blank: true, selected: value[:default].to_json} %>
|
30
|
+
<% elsif value[:type] == :boolean %>
|
31
|
+
<%= options_form.check_box "#{key}][default", :checked=>value[:default] == "1" %>
|
32
|
+
<% else %>
|
33
|
+
<%= options_form.text_field "#{key}][default", :value=>value[:default] %>
|
34
|
+
<% end %>
|
35
|
+
</div>
|
36
|
+
</div>
|
37
|
+
</div>
|
38
|
+
<% end %>
|
39
|
+
<% end %>
|
@@ -0,0 +1,57 @@
|
|
1
|
+
<%= nested_form_for(@workflow) do |f| %>
|
2
|
+
<% if @workflow.errors.any? %>
|
3
|
+
<div id="error_explanation">
|
4
|
+
<h2><%= pluralize(@workflow.errors.count, "error") %>
|
5
|
+
prohibited this workflow from being saved:</h2>
|
6
|
+
<ul>
|
7
|
+
<% @workflow.errors.full_messages.each do |msg| %>
|
8
|
+
<li><%= msg %></li>
|
9
|
+
<% end %>
|
10
|
+
</ul>
|
11
|
+
</div>
|
12
|
+
<% end %>
|
13
|
+
<div data-magellan-expedition="fixed">
|
14
|
+
<dl class="sub-nav">
|
15
|
+
<dd data-magellan-arrival="basic"><a href="#basic">Basic Details</a></dd>
|
16
|
+
<dd data-magellan-arrival="global_actions"><a href="#global_actions">Global Actions</a></dd>
|
17
|
+
<dd data-magellan-arrival="stages"><a href="#stages">Stages</a></dd>
|
18
|
+
</dl>
|
19
|
+
</div>
|
20
|
+
<a name="basic"></a>
|
21
|
+
<fieldset>
|
22
|
+
<legend data-magellan-destination="basic">Basic Details</legend>
|
23
|
+
<div class="field">
|
24
|
+
<%= f.label :name %>
|
25
|
+
<%= f.text_field :name %>
|
26
|
+
</div>
|
27
|
+
</fieldset>
|
28
|
+
<hr/>
|
29
|
+
<a name="global_actions"></a>
|
30
|
+
<h4 data-magellan-destination="global_actions">Global Actions<br/><small>These actions will be run every time the stage changes</small></h4>
|
31
|
+
<%= render partial: 'shared/actions/fields', locals: {f: f, label: 'global action', association: :actions} %>
|
32
|
+
<hr/>
|
33
|
+
<a name="stages"></a>
|
34
|
+
<h4 data-magellan-destination="stages">Stages<br/><small>The available states for the workflow</small></h4>
|
35
|
+
<%= f.fields_for :stages do |stage_form| %>
|
36
|
+
<fieldset>
|
37
|
+
<legend>Stage Details -
|
38
|
+
<%= stage_form.link_to_remove "Remove this stage" %></legend>
|
39
|
+
<div class="field">
|
40
|
+
<%= stage_form.label :name %>
|
41
|
+
<%= stage_form.text_field :name %>
|
42
|
+
</div>
|
43
|
+
<hr/>
|
44
|
+
<h5>Before Actions<br/><small>These actions will be run when leaving this stage</small></h5>
|
45
|
+
<%= render partial: 'shared/actions/fields', locals: {f: stage_form, association: :before_actions, label: 'before action'} %>
|
46
|
+
<hr/>
|
47
|
+
<h5>After Actions<br/><small>These actions will run before entering this stage</small></h5>
|
48
|
+
<%= render partial: 'shared/actions/fields', locals: {f: stage_form, association: :after_actions, label: 'after action'} %>
|
49
|
+
<hr/>
|
50
|
+
</fieldset>
|
51
|
+
<br/>
|
52
|
+
<% end %>
|
53
|
+
<br/>
|
54
|
+
<p><%= f.link_to_add "Add a stage", :stages %></p>
|
55
|
+
<%= f.submit class: "button" %>
|
56
|
+
<%= link_to 'Back', workflows_path, class: "button secondary" %>
|
57
|
+
<% end %>
|
@@ -0,0 +1,34 @@
|
|
1
|
+
<%= nested_form_for(@workflow) do |f| %>
|
2
|
+
<% if @workflow.errors.any? %>
|
3
|
+
<div id="error_explanation">
|
4
|
+
<h2><%= pluralize(@workflow.errors.count, "error") %>
|
5
|
+
prohibited this workflow from being saved:</h2>
|
6
|
+
<ul>
|
7
|
+
<% @workflow.errors.full_messages.each do |msg| %>
|
8
|
+
<li><%= msg %></li>
|
9
|
+
<% end %>
|
10
|
+
</ul>
|
11
|
+
</div>
|
12
|
+
<% end %>
|
13
|
+
<h2>Workflow Options</h2>
|
14
|
+
<div class="field">
|
15
|
+
<%= f.label :initial_stage %>
|
16
|
+
<%= f.collection_select :initial_stage_id, @workflow.stages, :id, :name, include_blank: true %>
|
17
|
+
</div>
|
18
|
+
<h2>Stage Transitions</h2>
|
19
|
+
<%= f.fields_for :stages do |stage_form| %>
|
20
|
+
<div class="field">
|
21
|
+
<h3><%= stage_form.object.name %></h3>
|
22
|
+
<%= stage_form.fields_for :stage_next_steps do |next_steps_form| %>
|
23
|
+
<div class="field">
|
24
|
+
<%= next_steps_form.label :next_step %>
|
25
|
+
<%= next_steps_form.collection_select :next_stage_id, @workflow.stages, :id, :name, include_blank: true %>
|
26
|
+
</div>
|
27
|
+
<%= next_steps_form.link_to_remove "Remove this step" %>
|
28
|
+
<% end %>
|
29
|
+
<p><%= stage_form.link_to_add "Add a next step", :stage_next_steps %></p>
|
30
|
+
</div>
|
31
|
+
<% end %>
|
32
|
+
<%= f.submit class: "button" %>
|
33
|
+
<%= link_to 'Back', workflows_path, class: "button secondary" %>
|
34
|
+
<% end %>
|
@@ -0,0 +1,16 @@
|
|
1
|
+
<table>
|
2
|
+
<tr>
|
3
|
+
<th>Name</th>
|
4
|
+
<th></th>
|
5
|
+
</tr>
|
6
|
+
<% @workflows.each do |workflow| %>
|
7
|
+
<tr>
|
8
|
+
<td><%= link_to workflow.name, workflow %></td>
|
9
|
+
<td>
|
10
|
+
<%= link_to 'Edit', edit_workflow_path(workflow), class: "button tiny" %>
|
11
|
+
<%= link_to 'Destroy', workflow, method: :delete, data: { confirm: 'Are you sure?' }, class: "button tiny alert" %></td>
|
12
|
+
</tr>
|
13
|
+
<% end %>
|
14
|
+
</table>
|
15
|
+
<br />
|
16
|
+
<%= link_to 'New Workflow', new_workflow_path, class: "button" %>
|
@@ -0,0 +1,49 @@
|
|
1
|
+
<h1>Workflow:
|
2
|
+
<%= @workflow.name %></h1>
|
3
|
+
<h5>Global Actions</h5>
|
4
|
+
<dl class="accordion" data-accordion>
|
5
|
+
<dd>
|
6
|
+
<a href="<%= "#workflow_#{@workflow.id}_actions" %>">Actions (<%= @workflow.actions.count %>)</a>
|
7
|
+
<div id="<%= "workflow_#{@workflow.id}_actions" %>" class="content">
|
8
|
+
<%= render partial: 'shared/actions/details', locals: {actions: @workflow.actions, uuid: "workflow_#{@workflow.id}_actions"} %>
|
9
|
+
</div>
|
10
|
+
</dd>
|
11
|
+
</dl>
|
12
|
+
<% @workflow.stages.each do |stage| %>
|
13
|
+
<dl class="accordion" data-accordion>
|
14
|
+
<dd>
|
15
|
+
<a href="#<%= "stage_#{stage.id}" %>"><%= stage.name %></a>
|
16
|
+
<div id="<%= "stage_#{stage.id}" %>" class="content">
|
17
|
+
<dl class="tabs" data-tab>
|
18
|
+
<dd class="active"><a href="<%= "#stage_#{stage.id}_before" %>">Before Actions (<%= stage.before_actions.count %>)</a></dd>
|
19
|
+
<dd><a href="<%= "#stage_#{stage.id}_after" %>">After Actions (<%= stage.after_actions.count %>)</a></dd>
|
20
|
+
<dd><a href="<%= "#stage_#{stage.id}_next_steps" %>">Next Steps (<%= stage.next_steps.count %>)</a></dd>
|
21
|
+
</dl>
|
22
|
+
<div class="tabs-content">
|
23
|
+
<div id="<%= "stage_#{stage.id}_before" %>" class="content active">
|
24
|
+
<%= render partial: 'shared/actions/details', locals: {actions: stage.before_actions, uuid: "stage_#{stage.id}_before"} %>
|
25
|
+
</div>
|
26
|
+
<div id="<%= "stage_#{stage.id}_after" %>" class="content">
|
27
|
+
<%= render partial: 'shared/actions/details', locals: {actions: stage.after_actions, uuid: "stage_#{stage.id}_after"} %>
|
28
|
+
</div>
|
29
|
+
<div id="<%= "stage_#{stage.id}_next_steps" %>" class="content">
|
30
|
+
<% if stage.next_steps.count == 0 %>
|
31
|
+
<b>No next steps defined</b>
|
32
|
+
<% else %>
|
33
|
+
<% stage.next_steps.each do |step| %>
|
34
|
+
<%= step.name %><br/>
|
35
|
+
<% end %>
|
36
|
+
<% end %>
|
37
|
+
</div>
|
38
|
+
</div>
|
39
|
+
</div>
|
40
|
+
</dd>
|
41
|
+
</dl>
|
42
|
+
<% end %>
|
43
|
+
<br/>
|
44
|
+
<%= link_to "Edit", edit_workflow_path(@workflow), class:"button" %>
|
45
|
+
<%= link_to "Configure Stages", configure_stages_workflow_path(@workflow), class:"button" %>
|
46
|
+
<%= link_to "Back", workflows_path , class:"button secondary"%>
|
47
|
+
<%= content_tag :svg, class: "workflow_diagram", data: {url: stages_workflow_url(@workflow, format: :json)} do %>
|
48
|
+
<g transform="translate(20, 20)" />
|
49
|
+
<% end %>
|
data/config/routes.rb
ADDED
@@ -0,0 +1,34 @@
|
|
1
|
+
# Copyright 2014 Netflix, Inc.
|
2
|
+
#
|
3
|
+
# Licensed under the Apache License, Version 2.0 (the "License");
|
4
|
+
# you may not use this file except in compliance with the License.
|
5
|
+
# You may obtain a copy of the License at
|
6
|
+
#
|
7
|
+
# http://www.apache.org/licenses/LICENSE-2.0
|
8
|
+
#
|
9
|
+
# Unless required by applicable law or agreed to in writing, software
|
10
|
+
# distributed under the License is distributed on an "AS IS" BASIS,
|
11
|
+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
12
|
+
# See the License for the specific language governing permissions and
|
13
|
+
# limitations under the License.
|
14
|
+
|
15
|
+
|
16
|
+
Workflowable::Engine.routes.draw do
|
17
|
+
resources :workflows do
|
18
|
+
member do
|
19
|
+
get 'stages'
|
20
|
+
get 'configure_stages'
|
21
|
+
post 'update_stages'
|
22
|
+
end
|
23
|
+
end
|
24
|
+
|
25
|
+
resources :actions, only: [] do
|
26
|
+
collection do
|
27
|
+
get 'options'
|
28
|
+
end
|
29
|
+
end
|
30
|
+
|
31
|
+
root to: "workflows#index"
|
32
|
+
|
33
|
+
|
34
|
+
end
|