diff --git a/app/assets/javascripts/application.js b/app/assets/javascripts/application.js index a148d45..48357d0 100644 --- a/app/assets/javascripts/application.js +++ b/app/assets/javascripts/application.js @@ -1,49 +1,89 @@ // This is a manifest file that'll be compiled into application.js, which will include all the files // listed below. // // Any JavaScript/Coffee file within this directory, lib/assets/javascripts, vendor/assets/javascripts, // or vendor/assets/javascripts of plugins, if any, can be referenced here using a relative path. // // It's not advisable to add code directly here, but if you do, it'll appear at the bottom of the // compiled file. // // Read Sprockets README (https://github.com/sstephenson/sprockets#sprockets-directives) for details // about supported directives. // //= require jquery.min //= require jquery_ujs //= require bootstrap.min //= require_tree . //= require highcharts //= require jobs //= require filesets $(document).ready(function() { - $(".schedule_run_form_plus").click(function() { - addScheduleRun(); - }); - $(".schedule_run_form_remove").click(function() { - removeScheduleRun(); - }); + if ($('.schedule_run_form_plus').size() > 0) { + $(".schedule_run_form_plus").click(function() { + addScheduleRun(); + return false; + }); + }; + if ($('.schedule_run_form_remove').size() > 0) { + $(".schedule_run_form_remove").click(function() { + removeScheduleRun(); + return false; + }); + }; + if ($('.schedule_run_form').size() > 1) { + $('.schedule_run_form_remove').show(); + }; }); function addScheduleRun() { - var scheduleRun = $('.schedule_run_form:last').clone(); - scheduleRun.insertAfter('.schedule_run_form:last'); - $('.schedule_run_form:last input').val(''); - if ($('.schedule_run_form').size() > 1) { - $(".schedule_run_form_remove").show(); - }; + var count = $('.schedule_run_form').size(); + var scheduleRun = $('.schedule_run_form:last').clone(); + + $(scheduleRun).find('label').each(function() { + var newLabel, oldLabel; + oldLabel = $(this).attr('for'); + newLabel = oldLabel.replace(new RegExp(/_[0-9]+_/), "_" + count + "_"); + $(this).attr('for', newLabel); + }); + + $(scheduleRun).find('select, input').each(function() { + var newId, oldId, newName, oldName; + oldId = $(this).attr('id'); + newId = oldId.replace(new RegExp(/_[0-9]+_/), "_" + count + "_"); + $(this).attr('id', newId); + + oldName = $(this).attr('name'); + newName = oldName.replace(new RegExp(/[0-9]+/), "[" + count + "]"); + $(this).attr('name', newName); + }); + + scheduleRun.insertAfter('.schedule_run_form:last'); + $('.schedule_run_form:last input').val(''); + if (count > 0) { + $(".schedule_run_form_remove").show(); + }; + $('.destroyer:last').remove(); } function removeScheduleRun() { - if ($('.schedule_run_form').size() > 1) { - $('.schedule_run_form:last').remove(); - if ($('.schedule_run_form').size() == 1) { - $(".schedule_run_form_remove").hide(); - }; - } - else { - alert('nothing to remove'); - }; + var count = $('.schedule_run_form').size(); + if (count > 1) { + var last_id = count - 1; + $('').attr({ + type: 'hidden', + class: 'destroyer', + id: 'schedule_schedule_runs_attributes_' + last_id + '__destroy', + name: 'schedule[schedule_runs_attributes][' + last_id + '][_destroy]', + value: '1' + }).appendTo('form'); + + $('.schedule_run_form:last').remove(); + if ($('.schedule_run_form').size() == 1) { + $(".schedule_run_form_remove").hide(); + }; + } + else { + alert('nothing to remove'); + }; } diff --git a/app/controllers/schedules_controller.rb b/app/controllers/schedules_controller.rb index 5345ba4..f213ea1 100644 --- a/app/controllers/schedules_controller.rb +++ b/app/controllers/schedules_controller.rb @@ -1,72 +1,78 @@ class SchedulesController < ApplicationController before_action :require_logged_in before_action :fetch_host, only: [:new, :create, :show, :edit, :update] before_action :fetch_job_id, only: [:new, :create, :show, :edit, :update] before_action :fetch_schedule, only: [:show, :edit, :update] def new @schedule = @host.schedules.new @schedule.schedule_runs.build end def show respond_to do |format| format.js {} end end def edit end def update if @schedule.update(fetch_params) flash[:success] = 'Schedule updated successfully' + participating_hosts = @schedule.participating_hosts + if participating_hosts.size.nonzero? + participating_hosts.each(&:recalculate) + flash[:alert] = "You will need to redeploy the afffected clients: " + + participating_hosts.map(&:name).join(', ') + end if @job_id redirect_to edit_host_job_path(@host, @job_id, schedule_id: @schedule.id) else redirect_to new_host_job_path(@host, schedule_id: @schedule.id) end else render :edit end end def create @schedule = @host.schedules.new(fetch_params) @schedule.runtime = params[:schedule][:runtime] if params[:schedule][:runtime] if @schedule.save flash[:success] = 'Schedule created successfully' if @job_id.present? redirect_to edit_host_job_path(@host, @job_id, schedule_id: @schedule.id) else redirect_to new_host_job_path(@host, schedule_id: @schedule.id) end else render :new end end def destroy end private def fetch_schedule @schedule = @host.schedules.find(params[:id]) end def fetch_host @host = current_user.hosts.find(params[:host_id]) end def fetch_job_id @job_id = @host.job_templates.find(params[:job_id]).id if params[:job_id].present? end def fetch_params params.require(:schedule). - permit(:name, { schedule_runs_attributes: [[:id, :level, :month, :day, :time]] }) + permit(:name, { schedule_runs_attributes: [[:id, :level, :month, :day, :time, :_destroy]] }) end end diff --git a/app/models/schedule.rb b/app/models/schedule.rb index 77afffc..f382c49 100644 --- a/app/models/schedule.rb +++ b/app/models/schedule.rb @@ -1,33 +1,41 @@ # Schedule model is the application representation of Bacula's Schedule. # It has references to a host and multiple schedule run in order to provide # the desired Bacula configuration class Schedule < ActiveRecord::Base has_many :schedule_runs belongs_to :host + has_many :job_templates validates :name, presence: true validates :name, uniqueness: { scope: :host } validates_with NameValidator - accepts_nested_attributes_for :schedule_runs + accepts_nested_attributes_for :schedule_runs, allow_destroy: true # Constructs an array where each element is a line for the Schedule's bacula config # # @return [Array] def to_bacula_config_array ['Schedule {'] + [" Name = \"#{name_for_config}\""] + schedule_runs.map {|r| " Run = #{r.schedule_line}" } + ['}'] end # Generates a name that will be used for the configuration file. # It is the name that will be sent to Bacula through the configuration # files. # # @return [String] def name_for_config [host.name, name].join(' ') end + + # Returns the hosts that have enabled jobs that use this schedule + # + # @return [ActiveRecord::Colletion] the participating hosts + def participating_hosts + Host.joins(:job_templates).where(job_templates: { enabled: true, schedule_id: id }).uniq + end end diff --git a/app/views/schedules/_form.html.erb b/app/views/schedules/_form.html.erb index 5926f30..2e9f830 100644 --- a/app/views/schedules/_form.html.erb +++ b/app/views/schedules/_form.html.erb @@ -1,49 +1,49 @@ <%= bootstrap_form_for(@schedule, url: url, method: method, layout: :horizontal, label_col: 'col-xs-3', control_col: 'col-xs-8') do |f| %> <%= f.text_field :name, required: true %>
eg: jan-mar, feb, monthly
<%= r.text_field :day, placeholder: '[week | week-range] day | day-range', required: true %>eg: first sun, second-fifth mon, mon-sat
<%= r.text_field :time, placeholder: 'HH:MM', required: true %> +