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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 6b2bb56ad2f157e6a7fe5d3cbee2bfab0e3fcef64f9137bd709ac37ea27949b9
4
- data.tar.gz: c2721a5074ba1fac6462ad95bef1012c7f00bfb74ff61a1eb6ae284f97c6b013
3
+ metadata.gz: 8edfa5f265e495edad2726cb2d812e0dea76978623cc7f9e0c03d2aaa27c7e90
4
+ data.tar.gz: 8d4b8737d9fb6d4b36977d873a078d57cbba1bbffebe0d357a12e62904de4025
5
5
  SHA512:
6
- metadata.gz: 3f0f933aa496d45610048de363e7fd189586dab4af85bfb012e2b93a55703104163f0183655f61a4a8c60d7f3a20c1f9c69c64d451eb601c3da73e68e0f7b4d1
7
- data.tar.gz: 78f35f561c65b366a7c21e20420d9235813b1368f1d06e0e87a35e888a0f8755317272854dd96224acae9ca42626635d44a1551d9b2e9853411348f45a87f2e1
6
+ metadata.gz: 36a38a82bc4b3b45b0879c5019e52417589a5868192828854091b9ead9e8f34384c7063325e0d1405e6bcfe18c318f11451630226354e0f966a2277ed5ba4e2f
7
+ data.tar.gz: 8b7d014f64cfd03d7d794d87f2556c115a4b095e23dbdb4b5e67f73f7e62b4f44924769c73ad66dec1b9362264f64df7e09fe7f92df549a044f8e62c9aa91498
@@ -0,0 +1,4 @@
1
+ /*
2
+ Place all the styles related to the matching controller here.
3
+ They will automatically be included in application.css.
4
+ */
@@ -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
- current_party_ids = [
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])
@@ -0,0 +1,6 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Wf
4
+ module StaticAssignmentsHelper
5
+ end
6
+ end
@@ -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
- workitem.transition.notification_callback.constantize.new(workitem, user.id).perform_now
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
- FireTransitionInternal.call(workitem)
14
- SweepAutomaticTransitions.call(workitem.case)
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
@@ -10,6 +10,7 @@ module Wf::CaseCommand
10
10
  end
11
11
 
12
12
  def call
13
+ raise("The workitem can not run by user.") unless workitem.real?
13
14
  raise("The workitem is not in state #{workitem.state}") unless workitem.enabled?
14
15
 
15
16
  # TODO: holding timeout
@@ -52,7 +52,7 @@ module Wf
52
52
  when "datetime"
53
53
  "datetime_field"
54
54
  when "boolean"
55
- "radio_button"
55
+ "check_box"
56
56
  when "text"
57
57
  "text_area"
58
58
  else
@@ -50,21 +50,11 @@ module Wf
50
50
  end
51
51
  end
52
52
 
53
- def check_exp(entry, workitem)
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
@@ -0,0 +1,11 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Wf
4
+ module MultipleInstances
5
+ class AllFinish
6
+ def perform(_workitem)
7
+ false
8
+ end
9
+ end
10
+ end
11
+ end
@@ -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
@@ -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.
@@ -4,21 +4,25 @@
4
4
  #
5
5
  # Table name: wf_workitems
6
6
  #
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
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">user</span>, <span class="badge badge-danger">form</span>, <span class="badge badge-danger">target</span>.</small>
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 %>
@@ -0,0 +1,3 @@
1
+ <div class="card card-body">
2
+ <%= render "form", static_assignment: @static_assignment %>
3
+ </div>
@@ -16,79 +16,114 @@
16
16
  </article>
17
17
  <% end %>
18
18
 
19
- <div class="form-group">
20
- <%= f.label :name, class: "label" %>
21
- <%= f.text_field :name, class: "form-control", placeholder: "Name" %>
22
- </div>
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
- <div class="form-group">
25
- <%= f.label :description, class: "label" %>
26
- <%= f.text_area :description, class: "form-control", placeholder: "Description" %>
27
- </div>
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
- <div class="form-group">
30
- <%= f.label :trigger_limit, class: "label" %>
31
- <%= f.text_field :trigger_limit, class: "form-control", placeholder: "Trigger Limit" %>
32
- </div>
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
- <div class="form-group">
35
- <%= f.label :sort_order, class: "label" %>
36
- <%= f.text_field :sort_order, class: "form-control", placeholder: "Sort Order" %>
37
- </div>
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
- <div class="form-group">
40
- <%= f.label :trigger_type, class: "label" %>
41
- <%= f.select :trigger_type, Wf::Transition.trigger_types.keys, {}, class: "form-control custom-select", placeholder: "Trigger Type" %>
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="form-group">
50
- <%= f.label :form, class: "label" %>
51
- <%= 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" %>
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="form-group">
55
- <%= f.label :enable_callback, class: "label" %>
56
- <%= f.select :enable_callback, Wf.enable_callbacks, {}, class: "form-control custom-select", placeholder: "Callback" %>
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="form-group">
60
- <%= f.label :fire_callback, class: "label" %>
61
- <%= f.select :fire_callback, Wf.fire_callbacks, {}, class: "form-control custom-select", placeholder: "Callback" %>
62
- </div>
69
+ <div class="card">
70
+ <h5 class="card-header">Callbacks</h5>
71
+ <div class="card-body">
63
72
 
64
- <div class="form-group">
65
- <%= f.label :deadline_callback, class: "label" %>
66
- <%= f.select :deadline_callback, Wf.deadline_callbacks, {}, class: "form-control custom-select", placeholder: "Callback" %>
67
- </div>
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
- <div class="form-group">
70
- <%= f.label :time_callback, class: "label" %>
71
- <%= f.select :time_callback, Wf.time_callbacks, {}, class: "form-control custom-select", placeholder: "Callback" %>
72
- </div>
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
- <div class="form-group">
75
- <%= f.label :hold_timeout_callback, class: "label" %>
76
- <%= f.select :hold_timeout_callback, Wf.hold_timeout_callbacks, {}, class: "form-control custom-select", placeholder: "Callback" %>
77
- </div>
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
- <div class="form-group">
80
- <%= f.label :assignment_callback, class: "label" %>
81
- <%= f.select :assignment_callback, Wf.assignment_callbacks, {}, class: "form-control custom-select", placeholder: "Callback" %>
82
- </div>
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
- <div class="form-group">
85
- <%= f.label :unassignment_callback, class: "label" %>
86
- <%= f.select :unassignment_callback, Wf.unassignment_callbacks, {}, class: "form-control custom-select", placeholder: "Callback" %>
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="form-group">
90
- <%= f.label :notification_callback, class: "label" %>
91
- <%= f.select :notification_callback, Wf.notification_callbacks, {}, class: "form-control custom-select", placeholder: "Callback" %>
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
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Wf
4
- VERSION = "0.1.8"
4
+ VERSION = "0.2.1"
5
5
  end
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.8
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-20 00:00:00.000000000 Z
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