Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Refs #10755 - Recurring logic, task groups
- Loading branch information
1 parent
0da7d80
commit b86be5c
Showing
31 changed files
with
966 additions
and
2 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,41 @@ | ||
function trigger_form_selector_binds(form_name, form_object_name) { | ||
var form = $('form#' + form_name); | ||
var trigger_mode_selector = form.find('input.trigger_mode_selector'); | ||
var input_type_selector = form.find('.form-control#input_type_selector'); | ||
|
||
trigger_mode_selector.on('click', function () { | ||
["future", "immediate", "recurring"].forEach(function(type) { | ||
form.find('fieldset.trigger_mode_form#trigger_mode_' + type).hide(); | ||
}); | ||
form.find('fieldset.trigger_mode_form#trigger_mode_' + $(this).val()).show(); | ||
}); | ||
|
||
input_type_selector.on('change', function () { | ||
var fieldset = form.find('fieldset.trigger_mode_form#trigger_mode_recurring'); | ||
['cronline', 'monthly', 'weekly', 'hourly', 'daily'].forEach(function(type) { | ||
fieldset.find('fieldset.input_type_form#input_type_' + type).hide(); | ||
}) | ||
fieldset.find('fieldset.input_type_form#input_type_' + $(this).val()).show(); | ||
var timepicker = fieldset.find('fieldset.input_type_form#time_picker'); | ||
if($(this).val() == 'cronline') { | ||
timepicker.hide(); | ||
} else { | ||
var hour_picker = timepicker.find('#s2id_triggering_time_time_4i'); | ||
if($(this).val() == 'hourly') { | ||
hour_picker.hide(); | ||
} else { | ||
hour_picker.show(); | ||
} | ||
timepicker.show(); | ||
} | ||
}); | ||
|
||
form.find('input.end_time_limit_selector').on('click', function() { | ||
var o = form.find('fieldset#trigger_mode_recurring fieldset#end_time_limit_form'); | ||
if($(this).val() === 'true') { | ||
o.show(); | ||
} else { | ||
o.hide(); | ||
}; | ||
}); | ||
}; |
33 changes: 33 additions & 0 deletions
33
app/controllers/foreman_tasks/recurring_logics_controller.rb
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,33 @@ | ||
module ForemanTasks | ||
class RecurringLogicsController < ::ApplicationController | ||
|
||
before_filter :find_recurring_logic, :only => [:show, :cancel] | ||
|
||
def index | ||
@recurring_logics = filter(resource_base) | ||
end | ||
|
||
def show | ||
end | ||
|
||
def cancel | ||
@recurring_logic.cancel | ||
redirect_to :action => :index | ||
end | ||
|
||
def controller_name | ||
'foreman_tasks_recurring_logics' | ||
end | ||
|
||
private | ||
|
||
def find_recurring_logic | ||
@recurring_logic ||= ::ForemanTasks::RecurringLogic.find(params[:id]) | ||
end | ||
|
||
def filter(scope) | ||
scope.search_for(params[:search]).paginate(:page => params[:page]) | ||
end | ||
|
||
end | ||
end |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,144 @@ | ||
module ForemanTasks | ||
module ForemanTasksHelper | ||
|
||
def recurring_logic_state(recurring_logic) | ||
icon, status = case recurring_logic.state | ||
when 'active' | ||
'glyphicon-info-sign' | ||
when 'finished' | ||
['glyphicon-ok-sign', 'status-ok'] | ||
when 'cancelled' | ||
['glyphicon-warning-sign', 'status-error'] | ||
else | ||
'glyphicon-question-sign' | ||
end | ||
content_tag(:i, ' '.html_safe, :class => "glyphicon #{icon}") + content_tag(:span, recurring_logic.humanized_state, :class => status) | ||
end | ||
|
||
def recurring_logic_action_buttons(recurring_logic) | ||
buttons = [] | ||
if authorized_for(:permission => :edit_recurring_logics, :auth_object => recurring_logic) | ||
buttons << link_to(N_("Cancel"), cancel_foreman_tasks_recurring_logic_path(recurring_logic), :method => :post, :class => 'btn btn-danger') unless %w(cancelled finished).include? recurring_logic.state | ||
end | ||
button_group buttons | ||
end | ||
|
||
def recurring_logic_next_occurrence(recurring_logic) | ||
if %w(finished cancelled).include? recurring_logic.state | ||
N_('-') | ||
else | ||
recurring_logic.next_occurrence_time | ||
end | ||
end | ||
|
||
def time_f(f, attr, field_options = {}, time_options = {}, html_options = {}) | ||
f.fields_for attr do |fields| | ||
field(fields, attr, field_options) do | ||
fields.time_select attr, time_options, html_options | ||
end | ||
end | ||
end | ||
|
||
def datetime_f(f, attr, field_options = {}, datetime_options = {}, html_options = {}) | ||
f.fields_for attr do |fields| | ||
field(fields, attr, field_options) do | ||
fields.datetime_select attr, datetime_options, html_options | ||
end | ||
end | ||
end | ||
|
||
def inline_checkboxes_f(f, attr, field_options = {}, checkboxes = {}, options = {}) | ||
field(f, attr, field_options) do | ||
checkboxes.map do |key, name| | ||
[f.check_box(key, options), " #{name} "] | ||
end.flatten.join('') | ||
end | ||
end | ||
|
||
def trigger_selector(f, triggering = Triggering.new, options = {}) | ||
render :partial => 'common/trigger_form', :locals => { :f => f, :triggering => triggering } | ||
end | ||
|
||
private | ||
|
||
def future_mode_fieldset(f, triggering) | ||
tags = [] | ||
tags << text_f(f, :start_at_raw, :label => _('Start at'), :placeholder => 'YYYY-mm-dd HH:MM') | ||
tags << text_f(f, :start_before_raw, :label => _('Start before'), :placeholder => 'YYYY-mm-dd HH:MM') | ||
content_tag(:fieldset, nil, :id => "trigger_mode_future", :class => "trigger_mode_form #{'hidden' unless triggering.future?}") do | ||
tags.join.html_safe | ||
end | ||
end | ||
|
||
def recurring_mode_fieldset(f, triggering) | ||
tags = [] | ||
tags << selectable_f(f, :input_type, %w(cronline monthly weekly daily hourly), {}, :label => _("Repeats"), :id => 'input_type_selector') | ||
tags += [ | ||
cronline_fieldset(f, triggering), | ||
monthly_fieldset(f, triggering), | ||
weekly_fieldset(f, triggering), | ||
time_picker_fieldset(f, triggering) | ||
] | ||
|
||
content_tag(:fieldset, nil, :id => 'trigger_mode_recurring', :class => "trigger_mode_form #{'hidden' unless triggering.recurring?}") do | ||
tags.join.html_safe | ||
end | ||
end | ||
|
||
def cronline_fieldset(f, triggering) | ||
options = [ | ||
_('is minute (range: 0-59)'), | ||
_('is hour (range: 0-23)'), | ||
_('is day of month (range: 1-31)'), | ||
_('is month (range: 1-12)'), | ||
_('is day of week (range: 0-6)') | ||
].map { |opt| content_tag(:li, opt) }.join | ||
help = content_tag(:span, nil, :class => 'help-inline') do | ||
popover(_('Explanation'), | ||
_("Cron line format 'a b c d e', where:<br><ol type=\"a\">#{options}</ol>")) | ||
end | ||
content_tag(:fieldset, nil, :class => "input_type_form #{'hidden' unless triggering.input_type == :cronline}", :id => "input_type_cronline") do | ||
text_f f, :cronline, :label => _('Cron line'), :placeholder => '* * * * *', :help_inline => help | ||
end | ||
end | ||
|
||
def monthly_fieldset(f, triggering) | ||
content_tag(:fieldset, nil, :id => "input_type_monthly", :class => "input_type_form #{'hidden' unless triggering.input_type == :monthly}") do | ||
text_f(f, :days, :label => _('Days'), :placeholder => '1,2...') | ||
end | ||
end | ||
|
||
def weekly_fieldset(f, triggering) | ||
content_tag(:fieldset, nil, :id => 'input_type_weekly', :class => "input_type_form #{'hidden' unless triggering.input_type == :weekly}") do | ||
f.fields_for :days_of_week do |days_of_week| | ||
inline_checkboxes_f(days_of_week, | ||
:weekday, | ||
{ :label => _("Days of week") }, | ||
{ 1 => _("Mon"), | ||
2 => _("Tue"), | ||
3 => _("Wed"), | ||
4 => _("Thu"), | ||
5 => _("Fri"), | ||
6 => _("Sat"), | ||
7 => _("Sun") }) | ||
end | ||
end | ||
end | ||
|
||
def time_picker_fieldset(f, triggering) | ||
tags = [] | ||
tags << content_tag(:fieldset, nil, :id => 'time_picker', :class => "input_type_form #{'hidden' if triggering.input_type == :cronline}") do | ||
time_f(f, :time, { :label => _("At"), :id => 'something' }, { :time_separator => '' }) | ||
end | ||
tags << number_f(f, :max_iteration, :label => _('Repeat N times'), :min => 1, :placeholder => 'N') | ||
tags << field(f, :end_time_limit_select, :label => _("Ends"), :control_group_id => "end_time_limit_select") do | ||
radio_button_f(f, :end_time_limited, :value => false, :checked=> true, :text => _("Never"), :class => 'end_time_limit_selector') + | ||
radio_button_f(f, :end_time_limited, :value => true, :text => _("On"), :class => 'end_time_limit_selector') | ||
end | ||
tags << content_tag(:fieldset, nil, :id => 'end_time_limit_form', :class => "input_type_form #{'hidden' unless triggering.end_time_limited}") do | ||
datetime_f f, :end_time, { :label => _("Ends at") }, { :use_month_numbers => true, :use_two_digit_numbers => true, :time_separator => '' } | ||
end | ||
tags.join.html_safe | ||
end | ||
end | ||
end |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,39 @@ | ||
module Actions | ||
module Middleware | ||
class InheritTaskGroups < Dynflow::Middleware | ||
|
||
def delay(*args) | ||
pass *args | ||
end | ||
|
||
def plan(*args) | ||
inherit_task_groups | ||
pass *args | ||
end | ||
|
||
def run(*args) | ||
pass *args | ||
collect_children_task_groups | ||
end | ||
|
||
def finalize | ||
pass | ||
end | ||
|
||
private | ||
|
||
def inherit_task_groups | ||
task.add_missing_task_groups(task.parent_task.task_groups) if task.parent_task | ||
end | ||
|
||
def collect_children_task_groups | ||
task.add_missing_task_groups task.sub_tasks.map(&:task_groups).flatten | ||
end | ||
|
||
def task | ||
@task ||= action.task | ||
end | ||
end | ||
end | ||
end | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,42 @@ | ||
module Actions | ||
module Middleware | ||
class RecurringLogic < ::Dynflow::Middleware | ||
|
||
# ::Actions::Middleware::RecurringLogic | ||
# | ||
# A middleware designed to make action repeatable. | ||
# After an action is delayed, it checks whether the delay_options | ||
# hash contains an id of a recurring logic. If so, it adds the task | ||
# to the recurring logic's task group, otherwise does nothing. | ||
# | ||
# After the action's plan phase the middleware checks if the task | ||
# is associated with a task group of any recurring logic, in which case | ||
# it triggers another repeat using the task group's recurring logic, | ||
# otherwise does nothing. | ||
def delay(delay_options, *args) | ||
pass(delay_options, *args).tap do | ||
if delay_options[:recurring_logic_id] | ||
task.add_missing_task_groups(recurring_logic(delay_options).task_group) | ||
end | ||
end | ||
end | ||
|
||
def plan(*args) | ||
pass(*args).tap do | ||
task_group = task.task_groups.find { |tg| tg.is_a? ::ForemanTasks::TaskGroups::RecurringLogicTaskGroup } | ||
task_group.recurring_logic.trigger_repeat(action.class, *args) if task_group | ||
end | ||
end | ||
|
||
private | ||
|
||
def recurring_logic(delay_options) | ||
ForemanTasks::RecurringLogic.find(delay_options[:recurring_logic_id]) | ||
end | ||
|
||
def task | ||
@task ||= action.task | ||
end | ||
end | ||
end | ||
end |
Oops, something went wrong.