petri_flow 0.1.8 → 0.2.1
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/app/assets/stylesheets/wf/static_assignments.css +4 -0
- data/app/controllers/wf/static_assignments_controller.rb +34 -0
- data/app/controllers/wf/transitions_controller.rb +8 -1
- data/app/controllers/wf/workitems_controller.rb +1 -5
- data/app/helpers/wf/static_assignments_helper.rb +6 -0
- data/app/models/wf/case_command/add_workitem_assignment.rb +18 -1
- data/app/models/wf/case_command/finish_workitem.rb +16 -2
- data/app/models/wf/case_command/start_workitem.rb +1 -0
- data/app/models/wf/field.rb +1 -1
- data/app/models/wf/guard.rb +2 -12
- data/app/models/wf/multiple_instances/all_finish.rb +11 -0
- data/app/models/wf/transition.rb +2 -1
- data/app/models/wf/transition_static_assignment.rb +6 -0
- data/app/models/wf/workflow.rb +6 -1
- data/app/models/wf/workitem.rb +64 -17
- data/app/views/wf/guards/_form.html.erb +1 -1
- data/app/views/wf/static_assignments/_form.html.erb +27 -0
- data/app/views/wf/static_assignments/new.html.erb +3 -0
- data/app/views/wf/transitions/_form.html.erb +90 -55
- data/app/views/wf/transitions/show.html.erb +83 -0
- data/config/routes.rb +4 -0
- data/db/migrate/20200222150432_add_multi_instance.rb +12 -0
- data/lib/wf/version.rb +1 -1
- data/lib/wf.rb +3 -0
- metadata +10 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 8edfa5f265e495edad2726cb2d812e0dea76978623cc7f9e0c03d2aaa27c7e90
|
4
|
+
data.tar.gz: 8d4b8737d9fb6d4b36977d873a078d57cbba1bbffebe0d357a12e62904de4025
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 36a38a82bc4b3b45b0879c5019e52417589a5868192828854091b9ead9e8f34384c7063325e0d1405e6bcfe18c318f11451630226354e0f966a2277ed5ba4e2f
|
7
|
+
data.tar.gz: 8b7d014f64cfd03d7d794d87f2556c115a4b095e23dbdb4b5e67f73f7e62b4f44924769c73ad66dec1b9362264f64df7e09fe7f92df549a044f8e62c9aa91498
|
@@ -0,0 +1,34 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require_dependency "wf/application_controller"
|
4
|
+
|
5
|
+
module Wf
|
6
|
+
class StaticAssignmentsController < ApplicationController
|
7
|
+
def new
|
8
|
+
@transition = Wf::Transition.find(params[:transition_id])
|
9
|
+
@static_assignment = @transition.transition_static_assignments.new
|
10
|
+
end
|
11
|
+
|
12
|
+
def create
|
13
|
+
@transition = Wf::Transition.find(params[:transition_id])
|
14
|
+
@party = Wf::Party.find(permit_params[:party_id])
|
15
|
+
@static_assignment = @transition.transition_static_assignments.new(party: @party)
|
16
|
+
if @static_assignment.save
|
17
|
+
redirect_to workflow_transition_path(@transition.workflow, @transition), notice: "static assignment was successfully created."
|
18
|
+
else
|
19
|
+
render :new
|
20
|
+
end
|
21
|
+
end
|
22
|
+
|
23
|
+
def destroy
|
24
|
+
@transition = Wf::Transition.find(params[:transition_id])
|
25
|
+
@static_assignment = @transition.transition_static_assignments.find(params[:id])
|
26
|
+
@static_assignment.destroy
|
27
|
+
render js: "window.location.reload()"
|
28
|
+
end
|
29
|
+
|
30
|
+
def permit_params
|
31
|
+
params.fetch(:transition_static_assignment, {}).permit(:party_id)
|
32
|
+
end
|
33
|
+
end
|
34
|
+
end
|
@@ -12,6 +12,11 @@ module Wf
|
|
12
12
|
breadcrumb @workflow.name, workflow_path(@workflow)
|
13
13
|
end
|
14
14
|
|
15
|
+
def show
|
16
|
+
@workflow = Wf::Workflow.find(params[:workflow_id])
|
17
|
+
@transition = @workflow.transitions.find(params[:id])
|
18
|
+
end
|
19
|
+
|
15
20
|
def create
|
16
21
|
@workflow = Wf::Workflow.find(params[:workflow_id])
|
17
22
|
tp = transition_params.merge(form: GlobalID::Locator.locate(transition_params[:form]))
|
@@ -65,7 +70,9 @@ module Wf
|
|
65
70
|
:unassignment_callback,
|
66
71
|
:notification_callback,
|
67
72
|
:deadline_callback,
|
68
|
-
:sub_workflow_id
|
73
|
+
:sub_workflow_id,
|
74
|
+
:multiple_instance,
|
75
|
+
:finish_condition
|
69
76
|
)
|
70
77
|
end
|
71
78
|
end
|
@@ -11,11 +11,7 @@ module Wf
|
|
11
11
|
breadcrumb "Workflows", :workflows_path
|
12
12
|
|
13
13
|
def index
|
14
|
-
|
15
|
-
wf_current_user,
|
16
|
-
Wf.org_classes.map { |org, _org_class| wf_current_user&.public_send(org) }
|
17
|
-
].flatten.map { |x| x&.party&.id }.compact
|
18
|
-
@workitems = Wf::Workitem.joins(:workitem_assignments).where(Wf::WorkitemAssignment.table_name => { party_id: current_party_ids })
|
14
|
+
@workitems = Wf::Workitem.todo(wf_current_user)
|
19
15
|
@workitems = @workitems.where(state: params[:state].intern) if params[:state]
|
20
16
|
@workitems = @workitems.where(state: params[:state].intern) if params[:state].present?
|
21
17
|
@workitems = @workitems.distinct.order("id desc").page(params[:page])
|
@@ -26,8 +26,25 @@ module Wf::CaseCommand
|
|
26
26
|
workitem.workitem_assignments.create!(party: party)
|
27
27
|
new_users = party.partable.users.to_a
|
28
28
|
to_notify = new_users - notified_users
|
29
|
+
transition = workitem.transition
|
29
30
|
to_notify.each do |user|
|
30
|
-
|
31
|
+
# TODO: multiple instance + sub workflow
|
32
|
+
if transition.multiple_instance? && !workitem.forked?
|
33
|
+
next if workitem.children.where(holding_user: user).exists?
|
34
|
+
|
35
|
+
child = workitem.children.create!(
|
36
|
+
workflow_id: workitem.workflow_id,
|
37
|
+
transition_id: workitem.transition_id,
|
38
|
+
state: :enabled,
|
39
|
+
trigger_time: workitem.trigger_time,
|
40
|
+
forked: true,
|
41
|
+
holding_user: user,
|
42
|
+
case_id: workitem.case_id
|
43
|
+
)
|
44
|
+
workitem.transition.notification_callback.constantize.new(child, user.id).perform_now
|
45
|
+
else
|
46
|
+
workitem.transition.notification_callback.constantize.new(workitem, user.id).perform_now
|
47
|
+
end
|
31
48
|
end
|
32
49
|
end
|
33
50
|
end
|
@@ -10,8 +10,22 @@ module Wf::CaseCommand
|
|
10
10
|
|
11
11
|
def call
|
12
12
|
Wf::ApplicationRecord.transaction do
|
13
|
-
|
14
|
-
|
13
|
+
if workitem.forked?
|
14
|
+
workitem.update!(finished_at: Time.zone.now, state: :finished)
|
15
|
+
Wf::Workitem.increment_counter(:children_finished_count, workitem.parent_id)
|
16
|
+
if parent = workitem.parent
|
17
|
+
if (parent.children_finished_count >= parent.children_count) || workitem.transition.finish_condition.constantize.new.perform(workitem)
|
18
|
+
parent.children.where(state: %i[started enabled]).find_each do |wi|
|
19
|
+
wi.update!(overridden_at: Time.zone.now, state: :overridden)
|
20
|
+
end
|
21
|
+
FireTransitionInternal.call(parent)
|
22
|
+
SweepAutomaticTransitions.call(parent.case)
|
23
|
+
end
|
24
|
+
end
|
25
|
+
else
|
26
|
+
FireTransitionInternal.call(workitem)
|
27
|
+
SweepAutomaticTransitions.call(workitem.case)
|
28
|
+
end
|
15
29
|
end
|
16
30
|
end
|
17
31
|
end
|
data/app/models/wf/field.rb
CHANGED
data/app/models/wf/guard.rb
CHANGED
@@ -50,21 +50,11 @@ module Wf
|
|
50
50
|
end
|
51
51
|
end
|
52
52
|
|
53
|
-
def check_exp(
|
54
|
-
form_hash = if entry
|
55
|
-
entry.for_mini_racer
|
56
|
-
else
|
57
|
-
{}
|
58
|
-
end
|
59
|
-
|
60
|
-
target_hash = workitem&.case&.targetable&.attributes || {}
|
61
|
-
user_hash = workitem&.holding_user&.attributes || {}
|
62
|
-
|
53
|
+
def check_exp(_entry, workitem)
|
63
54
|
# 1000ms, 200mb
|
64
55
|
context = MiniRacer::Context.new(timeout: 1000, max_memory: 200_000_000)
|
65
|
-
context.eval("let form = #{form_hash.to_json};")
|
66
|
-
context.eval("let user = #{user_hash.to_json};")
|
67
56
|
context.eval("let target = #{target_hash.to_json};")
|
57
|
+
context.eval("let workitem = #{workitem.to_json};")
|
68
58
|
exp_value = context.eval(exp)
|
69
59
|
yes_or_no?(exp_value, value)
|
70
60
|
end
|
data/app/models/wf/transition.rb
CHANGED
@@ -1,5 +1,4 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
|
-
|
3
2
|
# == Schema Information
|
4
3
|
#
|
5
4
|
# Table name: wf_transitions
|
@@ -24,6 +23,8 @@
|
|
24
23
|
# unassignment_callback :string default("Wf::Callbacks::UnassignmentDefault")
|
25
24
|
# form_type :string default("Wf::Form")
|
26
25
|
# sub_workflow_id :integer
|
26
|
+
# multiple_instance :boolean default("false")
|
27
|
+
# finish_condition :string default("Wf::MultipleInstances::AllFinish")
|
27
28
|
#
|
28
29
|
|
29
30
|
module Wf
|
@@ -17,5 +17,11 @@ module Wf
|
|
17
17
|
belongs_to :workflow
|
18
18
|
belongs_to :transition
|
19
19
|
belongs_to :party
|
20
|
+
|
21
|
+
validates :party_id, uniqueness: { scope: %i[workflow_id transition_id] }
|
22
|
+
|
23
|
+
before_validation do
|
24
|
+
self.workflow_id = transition&.workflow_id
|
25
|
+
end
|
20
26
|
end
|
21
27
|
end
|
data/app/models/wf/workflow.rb
CHANGED
@@ -119,8 +119,13 @@ module Wf
|
|
119
119
|
|
120
120
|
tg_mapping = {}
|
121
121
|
transitions.each do |t|
|
122
|
+
peripheries = if t.multiple_instance?
|
123
|
+
3
|
124
|
+
else
|
125
|
+
1
|
126
|
+
end
|
122
127
|
tg = graph.add_nodes(t.graph_id, label: t.name, shape: :box, style: :filled, fillcolor: "#d6ddfa", color: "#d6ddfa",
|
123
|
-
fontcolor: "#2c50ed", fontname: fontfamily,
|
128
|
+
fontcolor: "#2c50ed", fontname: fontfamily, peripheries: peripheries,
|
124
129
|
href: Wf::Engine.routes.url_helpers.edit_workflow_transition_path(self, t))
|
125
130
|
tg_mapping[t] = tg
|
126
131
|
# NOTICE: if sub_workflow is transition's workflow, then graph will loop infinite, this is valid for workflow definition.
|
data/app/models/wf/workitem.rb
CHANGED
@@ -4,21 +4,25 @@
|
|
4
4
|
#
|
5
5
|
# Table name: wf_workitems
|
6
6
|
#
|
7
|
-
# id
|
8
|
-
# case_id
|
9
|
-
# workflow_id
|
10
|
-
# transition_id
|
11
|
-
# state
|
12
|
-
# enabled_at
|
13
|
-
# started_at
|
14
|
-
# canceled_at
|
15
|
-
# finished_at
|
16
|
-
# overridden_at
|
17
|
-
# deadline
|
18
|
-
# created_at
|
19
|
-
# updated_at
|
20
|
-
# trigger_time
|
21
|
-
# holding_user_id
|
7
|
+
# id :integer not null, primary key
|
8
|
+
# case_id :integer
|
9
|
+
# workflow_id :integer
|
10
|
+
# transition_id :integer
|
11
|
+
# state :integer default("0")
|
12
|
+
# enabled_at :datetime
|
13
|
+
# started_at :datetime
|
14
|
+
# canceled_at :datetime
|
15
|
+
# finished_at :datetime
|
16
|
+
# overridden_at :datetime
|
17
|
+
# deadline :datetime
|
18
|
+
# created_at :datetime not null
|
19
|
+
# updated_at :datetime not null
|
20
|
+
# trigger_time :datetime
|
21
|
+
# holding_user_id :string
|
22
|
+
# children_count :integer default("0")
|
23
|
+
# children_finished_count :integer default("0")
|
24
|
+
# forked :boolean default("false")
|
25
|
+
# parent_id :integer
|
22
26
|
#
|
23
27
|
|
24
28
|
module Wf
|
@@ -26,6 +30,7 @@ module Wf
|
|
26
30
|
belongs_to :workflow
|
27
31
|
belongs_to :transition
|
28
32
|
belongs_to :case
|
33
|
+
belongs_to :parent, class_name: "Wf::Workitem", optional: true, counter_cache: :children_count
|
29
34
|
belongs_to :holding_user, foreign_key: :holding_user_id, class_name: Wf.user_class.to_s, optional: true
|
30
35
|
has_many :workitem_assignments
|
31
36
|
has_many :parties, through: :workitem_assignments, source: "party"
|
@@ -33,6 +38,8 @@ module Wf
|
|
33
38
|
has_many :entries, class_name: Wf.entry_class.to_s
|
34
39
|
has_one :started_case, foreign_key: :started_by_workitem_id, class_name: "Wf::Case"
|
35
40
|
|
41
|
+
has_many :children, foreign_key: :parent_id, class_name: "Wf::Workitem"
|
42
|
+
|
36
43
|
enum state: {
|
37
44
|
enabled: 0,
|
38
45
|
started: 1,
|
@@ -41,6 +48,39 @@ module Wf
|
|
41
48
|
overridden: 4
|
42
49
|
}
|
43
50
|
|
51
|
+
def self.todo(wf_current_user)
|
52
|
+
current_party_ids = [
|
53
|
+
wf_current_user,
|
54
|
+
Wf.org_classes.map { |org, _org_class| wf_current_user&.public_send(org) }
|
55
|
+
].flatten.map { |x| x&.party&.id }.compact
|
56
|
+
Wf::Workitem.where(forked: false).joins(:workitem_assignments).where(Wf::WorkitemAssignment.table_name => { party_id: current_party_ids })
|
57
|
+
end
|
58
|
+
|
59
|
+
def self.doing(wf_current_user)
|
60
|
+
where(holding_user: wf_current_user).where(state: %i[started enabled])
|
61
|
+
end
|
62
|
+
|
63
|
+
def self.done(wf_current_user)
|
64
|
+
where(holding_user: wf_current_user).where(state: [:finished])
|
65
|
+
end
|
66
|
+
|
67
|
+
def for_mini_racer
|
68
|
+
attr = attributes
|
69
|
+
attr = attr.merge(holding_user: holding_user&.attributes || {})
|
70
|
+
attr = attr.merge(form: entries.to_a.first&.for_mini_racer || {})
|
71
|
+
children_attrs = if forked?
|
72
|
+
[]
|
73
|
+
else
|
74
|
+
children.includes(:holding_user, entries: :field_values).map(&:for_mini_racer)
|
75
|
+
end
|
76
|
+
attr = attr.merge(children: children_attrs)
|
77
|
+
attr
|
78
|
+
end
|
79
|
+
|
80
|
+
def parent?
|
81
|
+
!forked
|
82
|
+
end
|
83
|
+
|
44
84
|
def name
|
45
85
|
"Workitem -> #{id}"
|
46
86
|
end
|
@@ -54,12 +94,19 @@ module Wf
|
|
54
94
|
end
|
55
95
|
end
|
56
96
|
|
97
|
+
def real?
|
98
|
+
return false if transition.multiple_instance? && parent_id.nil?
|
99
|
+
return false if transition.sub_workflow_id.present?
|
100
|
+
|
101
|
+
true
|
102
|
+
end
|
103
|
+
|
57
104
|
def started_by?(user)
|
58
|
-
enabled? && owned_by?(user)
|
105
|
+
real? && enabled? && owned_by?(user)
|
59
106
|
end
|
60
107
|
|
61
108
|
def finished_by?(user)
|
62
|
-
started? && owned_by?(user) && holding_user == user
|
109
|
+
real? && started? && owned_by?(user) && holding_user == user
|
63
110
|
end
|
64
111
|
|
65
112
|
def owned_by?(user)
|
@@ -22,7 +22,7 @@
|
|
22
22
|
</div>
|
23
23
|
|
24
24
|
<div class="form-group">
|
25
|
-
<%= f.label :exp, class: "label" %> <small>JavaScript with build-in variable <span class="badge badge-danger">
|
25
|
+
<%= f.label :exp, class: "label" %> <small>JavaScript with build-in variable <span class="badge badge-danger">workitem</span>, <span class="badge badge-danger">target</span>.</small>
|
26
26
|
<%= f.text_area :exp, class: "form-control", placeholder: "Exp", rows: 8 %>
|
27
27
|
</div>
|
28
28
|
|
@@ -0,0 +1,27 @@
|
|
1
|
+
<%= form_with(model: static_assignment, url: transition_static_assignments_path(static_assignment.transition), local: true) do |f| %>
|
2
|
+
<% if static_assignment.errors.any? %>
|
3
|
+
<article class="message is-danger">
|
4
|
+
<div class="message-header">
|
5
|
+
<p>
|
6
|
+
<%= pluralize(static_assignment.errors.count, "error") %> prohibited this static_assignment from being saved:
|
7
|
+
</p>
|
8
|
+
</div>
|
9
|
+
<div class="message-body content">
|
10
|
+
<ul>
|
11
|
+
<% static_assignment.errors.full_messages.each do |message| %>
|
12
|
+
<li><%= message %></li>
|
13
|
+
<% end %>
|
14
|
+
</ul>
|
15
|
+
</div>
|
16
|
+
</article>
|
17
|
+
<% end %>
|
18
|
+
|
19
|
+
<div class="form-group">
|
20
|
+
<%= f.label :party, class: "label" %>
|
21
|
+
<%= f.select :party_id, Wf::Party.all.map{|x| [x.party_name, x.id]}, {}, class: "form-control custom-select", placeholder: "fieldable" %>
|
22
|
+
</div>
|
23
|
+
|
24
|
+
<div class="form-group">
|
25
|
+
<%= f.submit class: "btn btn-primary", value: 'Create Static Assignment', data: {disable_with: 'Waiting...'} %>
|
26
|
+
</div>
|
27
|
+
<% end %>
|
@@ -16,79 +16,114 @@
|
|
16
16
|
</article>
|
17
17
|
<% end %>
|
18
18
|
|
19
|
-
<div class="
|
20
|
-
|
21
|
-
|
22
|
-
|
19
|
+
<div class="card">
|
20
|
+
<h5 class="card-header">Basic Information</h5>
|
21
|
+
<div class="card-body">
|
22
|
+
<div class="form-group">
|
23
|
+
<%= f.label :name, class: "label" %>
|
24
|
+
<%= f.text_field :name, class: "form-control", placeholder: "Name" %>
|
25
|
+
</div>
|
23
26
|
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
27
|
+
<div class="form-group">
|
28
|
+
<%= f.label :description, class: "label" %>
|
29
|
+
<%= f.text_area :description, class: "form-control", placeholder: "Description" %>
|
30
|
+
</div>
|
28
31
|
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
32
|
+
<div class="form-group">
|
33
|
+
<%= f.label :trigger_limit, class: "label" %>
|
34
|
+
<%= f.text_field :trigger_limit, class: "form-control", placeholder: "Trigger Limit" %>
|
35
|
+
</div>
|
33
36
|
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
37
|
+
<div class="form-group">
|
38
|
+
<%= f.label :sort_order, class: "label" %>
|
39
|
+
<%= f.text_field :sort_order, class: "form-control", placeholder: "Sort Order" %>
|
40
|
+
</div>
|
38
41
|
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
+
<div class="form-group">
|
43
|
+
<%= f.label :trigger_type, class: "label" %>
|
44
|
+
<%= f.select :trigger_type, Wf::Transition.trigger_types.keys, {}, class: "form-control custom-select", placeholder: "Trigger Type" %>
|
45
|
+
</div>
|
46
|
+
</div>
|
42
47
|
</div>
|
43
48
|
|
44
|
-
<div class="form-group">
|
45
|
-
<%= f.label :sub_workflow, class: "label" %>
|
46
|
-
<%= f.select :sub_workflow_id, options_for_select(Wf::Workflow.valid.all.map{|x| [x.name, x.id]} || []), {include_blank: 'Start a sub workflow?'}, class: "form-control custom-select", placeholder: "Sub Workflow" %>
|
47
|
-
</div>
|
48
49
|
|
49
|
-
<div class="
|
50
|
-
|
51
|
-
|
50
|
+
<div class="card">
|
51
|
+
<h5 class="card-header">Sub Workflow</h5>
|
52
|
+
<div class="card-body">
|
53
|
+
<div class="form-group">
|
54
|
+
<%= f.label :sub_workflow, class: "label" %>
|
55
|
+
<%= f.select :sub_workflow_id, options_for_select(Wf::Workflow.valid.all.map{|x| [x.name, x.id]} || []), {include_blank: 'Start a sub workflow?'}, class: "form-control custom-select", placeholder: "Sub Workflow" %>
|
56
|
+
</div>
|
52
57
|
</div>
|
53
58
|
|
54
|
-
<div class="
|
55
|
-
|
56
|
-
|
59
|
+
<div class="card">
|
60
|
+
<h5 class="card-header">Dynimac Form</h5>
|
61
|
+
<div class="card-body">
|
62
|
+
<div class="form-group">
|
63
|
+
<%= f.label :form, class: "label" %>
|
64
|
+
<%= f.select :form, options_for_select(Wf.form_class.constantize.all.map{|x| [x.name, x.to_global_id]} || [], selected: f.object&.form&.to_global_id), {include_blank: 'user can input from custom form?'}, class: "form-control custom-select", placeholder: "Form" %>
|
65
|
+
</div>
|
66
|
+
</div>
|
57
67
|
</div>
|
58
68
|
|
59
|
-
<div class="
|
60
|
-
|
61
|
-
|
62
|
-
</div>
|
69
|
+
<div class="card">
|
70
|
+
<h5 class="card-header">Callbacks</h5>
|
71
|
+
<div class="card-body">
|
63
72
|
|
64
|
-
|
65
|
-
|
66
|
-
|
67
|
-
|
73
|
+
<div class="form-group">
|
74
|
+
<%= f.label :enable_callback, class: "label" %>
|
75
|
+
<%= f.select :enable_callback, Wf.enable_callbacks, {}, class: "form-control custom-select", placeholder: "Callback" %>
|
76
|
+
</div>
|
68
77
|
|
69
|
-
|
70
|
-
|
71
|
-
|
72
|
-
|
78
|
+
<div class="form-group">
|
79
|
+
<%= f.label :fire_callback, class: "label" %>
|
80
|
+
<%= f.select :fire_callback, Wf.fire_callbacks, {}, class: "form-control custom-select", placeholder: "Callback" %>
|
81
|
+
</div>
|
73
82
|
|
74
|
-
|
75
|
-
|
76
|
-
|
77
|
-
|
83
|
+
<div class="form-group">
|
84
|
+
<%= f.label :deadline_callback, class: "label" %>
|
85
|
+
<%= f.select :deadline_callback, Wf.deadline_callbacks, {}, class: "form-control custom-select", placeholder: "Callback" %>
|
86
|
+
</div>
|
78
87
|
|
79
|
-
|
80
|
-
|
81
|
-
|
82
|
-
|
88
|
+
<div class="form-group">
|
89
|
+
<%= f.label :time_callback, class: "label" %>
|
90
|
+
<%= f.select :time_callback, Wf.time_callbacks, {}, class: "form-control custom-select", placeholder: "Callback" %>
|
91
|
+
</div>
|
83
92
|
|
84
|
-
|
85
|
-
|
86
|
-
|
93
|
+
<div class="form-group">
|
94
|
+
<%= f.label :hold_timeout_callback, class: "label" %>
|
95
|
+
<%= f.select :hold_timeout_callback, Wf.hold_timeout_callbacks, {}, class: "form-control custom-select", placeholder: "Callback" %>
|
96
|
+
</div>
|
97
|
+
|
98
|
+
<div class="form-group">
|
99
|
+
<%= f.label :assignment_callback, class: "label" %>
|
100
|
+
<%= f.select :assignment_callback, Wf.assignment_callbacks, {}, class: "form-control custom-select", placeholder: "Callback" %>
|
101
|
+
</div>
|
102
|
+
|
103
|
+
<div class="form-group">
|
104
|
+
<%= f.label :unassignment_callback, class: "label" %>
|
105
|
+
<%= f.select :unassignment_callback, Wf.unassignment_callbacks, {}, class: "form-control custom-select", placeholder: "Callback" %>
|
106
|
+
</div>
|
107
|
+
|
108
|
+
<div class="form-group">
|
109
|
+
<%= f.label :notification_callback, class: "label" %>
|
110
|
+
<%= f.select :notification_callback, Wf.notification_callbacks, {}, class: "form-control custom-select", placeholder: "Callback" %>
|
111
|
+
</div>
|
112
|
+
</div>
|
87
113
|
</div>
|
88
114
|
|
89
|
-
<div class="
|
90
|
-
|
91
|
-
|
115
|
+
<div class="card">
|
116
|
+
<h5 class="card-header">Multiple Instances</h5>
|
117
|
+
<div class="card-body">
|
118
|
+
<div class="form-group">
|
119
|
+
<%= f.label :multiple_instance, class: "label" %>
|
120
|
+
<%= f.check_box :multiple_instance %>
|
121
|
+
</div>
|
122
|
+
<div class="form-group">
|
123
|
+
<%= f.label :finish_condition, class: "label" %>
|
124
|
+
<%= f.select :finish_condition, Wf.finish_conditions, {}, class: "form-control custom-select", placeholder: "Finish_condition" %>
|
125
|
+
</div>
|
126
|
+
</div>
|
92
127
|
</div>
|
93
128
|
|
94
129
|
<div class="form-group">
|
@@ -0,0 +1,83 @@
|
|
1
|
+
<div class="card card-body">
|
2
|
+
<div class="float-right">
|
3
|
+
<%= link_to 'Edit Transition', edit_workflow_transition_path(@workflow, @transition), class: 'btn btn-primary' %>
|
4
|
+
<%= link_to 'Create Static Assignments', new_transition_static_assignment_path(@transition), class: 'btn btn-primary' %>
|
5
|
+
</div>
|
6
|
+
<div>
|
7
|
+
<h2>Transition Detail</h2>
|
8
|
+
<table class="table table-view">
|
9
|
+
<tbody>
|
10
|
+
<tr>
|
11
|
+
<th scope="row">ID</th>
|
12
|
+
<td><%= @transition.id %></td>
|
13
|
+
</tr>
|
14
|
+
<tr>
|
15
|
+
<th scope="row">Name</th>
|
16
|
+
<td><%= @transition.name %></td>
|
17
|
+
</tr>
|
18
|
+
<tr>
|
19
|
+
<th scope="row">Trigger Limit</th>
|
20
|
+
<td><%= @transition.trigger_limit %></td>
|
21
|
+
</tr>
|
22
|
+
<tr>
|
23
|
+
<th scope="row">Trigger Type</th>
|
24
|
+
<td><%= @transition.trigger_type %></td>
|
25
|
+
</tr>
|
26
|
+
<tr>
|
27
|
+
<th>Form</th>
|
28
|
+
<td>
|
29
|
+
<% if @transition.form %>
|
30
|
+
<%= link_to @transition.form.name, form_path(@transition.form) %>
|
31
|
+
<% else %>
|
32
|
+
No Form
|
33
|
+
<% end %>
|
34
|
+
</td>
|
35
|
+
</tr>
|
36
|
+
|
37
|
+
<tr>
|
38
|
+
<th>Sub Workflow</th>
|
39
|
+
<td>
|
40
|
+
<% if @transition.sub_workflow %>
|
41
|
+
<%= link_to @transition.sub_workflow.name, workflow_path(@transition.sub_workflow_id) %>
|
42
|
+
<% else %>
|
43
|
+
No
|
44
|
+
<% end %>
|
45
|
+
</td>
|
46
|
+
</tr>
|
47
|
+
|
48
|
+
<tr>
|
49
|
+
<th scope="row">Multiple Instance?</th>
|
50
|
+
<td><%= @transition.multiple_instance %></td>
|
51
|
+
</tr>
|
52
|
+
<tr>
|
53
|
+
<th scope="row">Finish Condition</th>
|
54
|
+
<td><%= @transition.finish_condition %></td>
|
55
|
+
</tr>
|
56
|
+
</tbody>
|
57
|
+
</table>
|
58
|
+
</div>
|
59
|
+
|
60
|
+
<div>
|
61
|
+
<h2>Static Assignments</h2>
|
62
|
+
<table class="table table-view">
|
63
|
+
<thead>
|
64
|
+
<tr>
|
65
|
+
<th scope="col">ID</th>
|
66
|
+
<th scope="col">Party Name</th>
|
67
|
+
<th scope="col">Party Type</th>
|
68
|
+
<th scope="col">Actions</th>
|
69
|
+
</tr>
|
70
|
+
</thead>
|
71
|
+
<tbody>
|
72
|
+
<% @transition.transition_static_assignments.each do |assign| %>
|
73
|
+
<tr>
|
74
|
+
<td><%= assign.id %></td>
|
75
|
+
<td><%= assign.party.party_name %></td>
|
76
|
+
<td><%= assign.party.partable_type %></td>
|
77
|
+
<td><%= link_to 'Delete', transition_static_assignment_path(@transition, assign), remote: true, method: :delete, data: {confirm: 'confirm?'}, class: 'btn btn-sm btn-info' %></td>
|
78
|
+
</tr>
|
79
|
+
<% end %>
|
80
|
+
</tbody>
|
81
|
+
</table>
|
82
|
+
</div>
|
83
|
+
</div>
|
data/config/routes.rb
CHANGED
@@ -16,6 +16,10 @@ Wf::Engine.routes.draw do
|
|
16
16
|
resources :fields
|
17
17
|
end
|
18
18
|
|
19
|
+
resources :transitions do
|
20
|
+
resources :static_assignments
|
21
|
+
end
|
22
|
+
|
19
23
|
resources :workitems do
|
20
24
|
resources :workitem_assignments, only: %i[new create destroy]
|
21
25
|
resources :comments, only: %i[new create destroy]
|
@@ -0,0 +1,12 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
class AddMultiInstance < ActiveRecord::Migration[6.0]
|
4
|
+
def change
|
5
|
+
add_column :wf_transitions, :multiple_instance, :boolean, default: false, comment: "multiple instance mode or not"
|
6
|
+
add_column :wf_transitions, :finish_condition, :string, comment: "set finish condition for parent workitem.", default: "Wf::MultipleInstances::AllFinish"
|
7
|
+
add_column :wf_workitems, :children_count, :integer, default: 0
|
8
|
+
add_column :wf_workitems, :children_finished_count, :integer, default: 0
|
9
|
+
add_column :wf_workitems, :forked, :boolean, default: false
|
10
|
+
add_column :wf_workitems, :parent_id, :bigint, comment: "parent workitem id"
|
11
|
+
end
|
12
|
+
end
|
data/lib/wf/version.rb
CHANGED
data/lib/wf.rb
CHANGED
@@ -19,6 +19,8 @@ module Wf
|
|
19
19
|
|
20
20
|
attr_accessor :user_class
|
21
21
|
attr_accessor :org_classes
|
22
|
+
|
23
|
+
attr_accessor :finish_conditions
|
22
24
|
end
|
23
25
|
|
24
26
|
self.enable_callbacks = ["Wf::Callbacks::EnableDefault"]
|
@@ -34,4 +36,5 @@ module Wf
|
|
34
36
|
self.field_class = "::Wf::Field"
|
35
37
|
self.user_class = "::Wf::User"
|
36
38
|
self.org_classes = { group: "::Wf::Group" }
|
39
|
+
self.finish_conditions = ["Wf::MultipleInstances::AllFinish"]
|
37
40
|
end
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: petri_flow
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.1
|
4
|
+
version: 0.2.1
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Hooopo Wang
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2020-02-
|
11
|
+
date: 2020-02-26 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: bootstrap
|
@@ -204,6 +204,7 @@ files:
|
|
204
204
|
- app/assets/stylesheets/wf/forms.css
|
205
205
|
- app/assets/stylesheets/wf/guards.css
|
206
206
|
- app/assets/stylesheets/wf/places.css
|
207
|
+
- app/assets/stylesheets/wf/static_assignments.css
|
207
208
|
- app/assets/stylesheets/wf/transitions.css
|
208
209
|
- app/assets/stylesheets/wf/uikit/_colors.scss
|
209
210
|
- app/assets/stylesheets/wf/uikit/_variables.scss
|
@@ -224,6 +225,7 @@ files:
|
|
224
225
|
- app/controllers/wf/forms_controller.rb
|
225
226
|
- app/controllers/wf/guards_controller.rb
|
226
227
|
- app/controllers/wf/places_controller.rb
|
228
|
+
- app/controllers/wf/static_assignments_controller.rb
|
227
229
|
- app/controllers/wf/transitions_controller.rb
|
228
230
|
- app/controllers/wf/workflows_controller.rb
|
229
231
|
- app/controllers/wf/workitem_assignments_controller.rb
|
@@ -236,6 +238,7 @@ files:
|
|
236
238
|
- app/helpers/wf/forms_helper.rb
|
237
239
|
- app/helpers/wf/guards_helper.rb
|
238
240
|
- app/helpers/wf/places_helper.rb
|
241
|
+
- app/helpers/wf/static_assignments_helper.rb
|
239
242
|
- app/helpers/wf/transitions_helper.rb
|
240
243
|
- app/helpers/wf/workflows_helper.rb
|
241
244
|
- app/helpers/wf/workitem_assignments_helper.rb
|
@@ -293,6 +296,7 @@ files:
|
|
293
296
|
- app/models/wf/form.rb
|
294
297
|
- app/models/wf/group.rb
|
295
298
|
- app/models/wf/guard.rb
|
299
|
+
- app/models/wf/multiple_instances/all_finish.rb
|
296
300
|
- app/models/wf/party.rb
|
297
301
|
- app/models/wf/place.rb
|
298
302
|
- app/models/wf/token.rb
|
@@ -330,9 +334,12 @@ files:
|
|
330
334
|
- app/views/wf/places/_form.html.erb
|
331
335
|
- app/views/wf/places/edit.html.erb
|
332
336
|
- app/views/wf/places/new.html.erb
|
337
|
+
- app/views/wf/static_assignments/_form.html.erb
|
338
|
+
- app/views/wf/static_assignments/new.html.erb
|
333
339
|
- app/views/wf/transitions/_form.html.erb
|
334
340
|
- app/views/wf/transitions/edit.html.erb
|
335
341
|
- app/views/wf/transitions/new.html.erb
|
342
|
+
- app/views/wf/transitions/show.html.erb
|
336
343
|
- app/views/wf/workflows/_form.html.erb
|
337
344
|
- app/views/wf/workflows/edit.html.erb
|
338
345
|
- app/views/wf/workflows/index.html.erb
|
@@ -353,6 +360,7 @@ files:
|
|
353
360
|
- db/migrate/20200213130900_remove_workflow_id_from_form_related.rb
|
354
361
|
- db/migrate/20200220070839_remove_unused_column.rb
|
355
362
|
- db/migrate/20200220072512_add_sub_workflow.rb
|
363
|
+
- db/migrate/20200222150432_add_multi_instance.rb
|
356
364
|
- lib/tasks/wf_tasks.rake
|
357
365
|
- lib/wf.rb
|
358
366
|
- lib/wf/engine.rb
|