diff --git a/app/controllers/admin/clients_controller.rb b/app/controllers/admin/clients_controller.rb
index 3d9ccfa..5d20566 100644
--- a/app/controllers/admin/clients_controller.rb
+++ b/app/controllers/admin/clients_controller.rb
@@ -1,51 +1,53 @@
class Admin::ClientsController < Admin::BaseController
before_action :fetch_client, only: [:show, :jobs, :logs, :stats]
before_action :fetch_logs, only: [:logs]
# Shows all available clients
#
# GET /admin/clients
def index
@clients = Client.includes(:jobs).all
@client_ids = @clients.map(&:id)
fetch_jobs_info
end
# Shows a specific client
#
# GET /admin/clients/1
def show
get_charts
end
# GET /admin/clients/1/jobs
- def jobs; end
+ def jobs
+ @jobs = @client.recent_jobs.page(params[:page])
+ end
# GET /admin/clients/1/logs
def logs
end
# GET /admin/clients/1/stats
# POST /admin/clients/1/stats
def stats
get_charts
end
private
# Fetches the client based on the given id
def fetch_client
@client = Client.find(params[:id])
@client_ids = [@client.id]
end
def fetch_jobs_info
@stats = JobStats.new
end
def get_charts
days_ago = params.fetch(:days_back, 7).to_i rescue 7
@job_status = ChartGenerator.job_statuses(@client_ids, days_ago)
@job_stats = ChartGenerator.job_stats(@client_ids, days_ago - 1)
end
end
diff --git a/app/controllers/application_controller.rb b/app/controllers/application_controller.rb
index dda37b9..39ebcf6 100644
--- a/app/controllers/application_controller.rb
+++ b/app/controllers/application_controller.rb
@@ -1,25 +1,26 @@
class ApplicationController < ActionController::Base
# Prevent CSRF attacks by raising an exception.
# For APIs, you may want to use :null_session instead.
protect_from_forgery with: :exception
helper_method :current_user
protected
def current_user
@current_user ||= User.last
end
def fetch_logs
days_ago = params.fetch(:days_back, 7).to_i rescue 7
if @client
@logs = Log.includes(:job).joins(job: :client).where(Client: { ClientId: @client.id })
else
@logs = Log.includes(:job).joins(job: { client: { host: :users } }).
where(users: { id: current_user.id })
end
- @logs = @logs.where('Time > ?', days_ago.days.ago).order(Time: :desc)#.limit(10)
+ @logs = @logs.where('Time > ?', days_ago.days.ago).
+ order(Time: :desc, LogId: :desc).page(params[:page])
end
end
diff --git a/app/controllers/clients_controller.rb b/app/controllers/clients_controller.rb
index e18d752..273c25d 100644
--- a/app/controllers/clients_controller.rb
+++ b/app/controllers/clients_controller.rb
@@ -1,47 +1,49 @@
class ClientsController < ApplicationController
before_action :set_client, only: [:show, :jobs, :logs, :stats]
before_action :fetch_logs, only: [:logs]
# GET /clients
# POST /clients
def index
@client_ids = Client.for_user(current_user.id).pluck(:ClientId)
@clients = Client.where(ClientId: @client_ids).includes(:jobs)
@hosts = current_user.hosts.not_baculized
fetch_jobs_info
get_charts
end
# GET /clients/1
def show
end
# GET /clients/1/jobs
- def jobs; end
+ def jobs
+ @jobs = @client.recent_jobs.page(params[:page])
+ end
# GET /clients/1/logs
def logs; end
# GET /clients/1/stats
# POST /clients/1/stats
def stats
get_charts
end
private
def set_client
@client = Client.for_user(current_user.id).find(params[:id])
@client_ids = [@client.id]
end
def fetch_jobs_info
@stats = JobStats.new(@client_ids)
end
def get_charts
days_ago = params.fetch(:days_back, 7).to_i rescue 7
@job_status = ChartGenerator.job_statuses(@client_ids, days_ago)
@job_stats = ChartGenerator.job_stats(@client_ids, days_ago - 1)
end
end
diff --git a/app/models/client.rb b/app/models/client.rb
index eb68a58..bb6de09 100644
--- a/app/models/client.rb
+++ b/app/models/client.rb
@@ -1,91 +1,90 @@
class Client < ActiveRecord::Base
self.table_name = :Client
self.primary_key = :ClientId
alias_attribute :name, :Name
alias_attribute :uname, :Uname
alias_attribute :auto_prune, :AutoPrune
alias_attribute :file_retention, :FileRetention
alias_attribute :job_retention, :JobRetention
has_many :jobs, foreign_key: :ClientId
has_one :host, foreign_key: :name, primary_key: :Name
scope :for_user, ->(user_id) { joins(host: :users).where(users: { id: user_id }) }
DAY_SECS = 60 * 60 * 24
- RECENT_JOBS_COUNT = 5
# Fetches the client's job_templates that are already persisted to
# Bacula's configuration
#
# @return [ActiveRecord::Relation] of `JobTemplate`
def persisted_jobs
host.job_templates.where(baculized: true).includes(:fileset, :schedule)
end
# Fetches the client's performed jobs in reverse chronological order
#
# @return [ActiveRecord::Relation] of `Job`
def recent_jobs
- jobs.order(EndTime: :desc).limit(RECENT_JOBS_COUNT).includes(:file_set)
+ jobs.order(EndTime: :desc).includes(:file_set)
end
# Helper method. It shows the client's job retention,
# (which is expressed in seconds) in days.
#
# @return [Integer]
def job_retention_days
job_retention / DAY_SECS
end
# Helper method. It shows the client's file retention,
# (which is expressed in seconds) in days.
#
# @return [Integer]
def file_retention_days
file_retention / DAY_SECS
end
# Helper method for auto_prune
#
# @return [String] 'yes' or 'no'
def auto_prune_human
auto_prune == 1 ? 'yes' : 'no'
end
# Helper method for displayin the last job's datetime in a nice format.
def last_job_date_formatted
if job_time = jobs.backup_type.last.try(:end_time)
I18n.l(job_time, format: :long)
end
end
# Shows if a client has any backup jobs to Bacule config
#
# @return [Boolean]
def is_backed_up?
jobs.backup_type.any?
end
# Shows the total file size of the jobs that run for a specific client
#
# @return [Integer] Size in Bytes
def backup_jobs_size
jobs.backup_type.map(&:job_bytes).sum
end
# Shows the total files' count for the jobs that run for a specific client
#
# @return [Integer] File count
def files_count
jobs.map(&:job_files).sum
end
# Fetches the client's jobs that are running at the moment
#
# @return [Integer]
def running_jobs
jobs.running.count
end
end
diff --git a/app/models/job.rb b/app/models/job.rb
index 7f5fc83..21f404a 100644
--- a/app/models/job.rb
+++ b/app/models/job.rb
@@ -1,97 +1,99 @@
class Job < ActiveRecord::Base
self.table_name = :Job
self.primary_key = :JobId
alias_attribute :job_id, :JobId
alias_attribute :job, :Job
alias_attribute :name, :Name
alias_attribute :type, :Type
alias_attribute :level, :Level
alias_attribute :client_id, :ClientId
alias_attribute :job_status, :JobStatus
alias_attribute :sched_time, :SchedTime
alias_attribute :start_time, :StartTime
alias_attribute :end_time, :EndTime
alias_attribute :real_end_time, :RealEndTime
alias_attribute :job_t_date, :JobTDate
alias_attribute :vol_session_id, :VolSessionId
alias_attribute :vol_session_time, :VolSessionTime
alias_attribute :job_files, :JobFiles
alias_attribute :job_bytes, :JobBytes
alias_attribute :read_bytes, :ReadBytes
alias_attribute :job_errors, :JobErrors
alias_attribute :job_missing_files, :JobMissingFiles
alias_attribute :pool_id, :PoolId
alias_attribute :file_set_id, :FileSetId
alias_attribute :prior_job_id, :PriorJobId
alias_attribute :purged_files, :PurgedFiles
alias_attribute :has_base, :HasBase
alias_attribute :has_cache, :HasCache
alias_attribute :reviewed, :Reviewed
alias_attribute :comment, :Comment
belongs_to :pool, foreign_key: :PoolId
belongs_to :file_set, foreign_key: :FileSetId
belongs_to :client, foreign_key: :ClientId
has_many :bacula_files, foreign_key: :JobId
has_many :base_files, foreign_key: :BaseJobId
has_many :job_media, foreign_key: :JobId
has_many :logs, foreign_key: :JobId
scope :running, -> { where(job_status: 'R') }
scope :backup_type, -> { where(type: 'B') }
scope :restore_type, -> { where(type: 'R') }
HUMAN_STATUS = {
'A' => 'Canceled by user',
'B' => 'Blocked',
'C' => 'Created, not yet running',
'D' => 'Verify found differences',
'E' => 'Terminated with errors',
'F' => 'Waiting for Client',
'M' => 'Waiting for media mount',
'R' => 'Running',
'S' => 'Waiting for Storage daemon',
'T' => 'Completed successfully',
'a' => 'SD despooling attributes',
'c' => 'Waiting for client resource',
'd' => 'Waiting on maximum jobs',
'e' => 'Non-fatal error',
'f' => 'Fatal error',
'i' => 'Doing batch insert file records',
'j' => 'Waiting for job resource',
'm' => 'Waiting for new media',
'p' => 'Waiting on higher priority jobs',
's' => 'Waiting for storage resource',
't' => 'Waiting on start time'
}
+ paginates_per 20
+
def level_human
{
'F' => 'Full',
'D' => 'Differential',
'I' => 'Incremental'
}[level]
end
def status_human
HUMAN_STATUS[job_status]
end
def fileset
file_set.try(:file_set) || '-'
end
def start_time_formatted
if start_time
I18n.l(start_time, format: :long)
end
end
def end_time_formatted
if end_time
I18n.l(end_time, format: :long)
end
end
end
diff --git a/app/models/log.rb b/app/models/log.rb
index 3955614..2a67b3e 100644
--- a/app/models/log.rb
+++ b/app/models/log.rb
@@ -1,17 +1,19 @@
class Log < ActiveRecord::Base
self.table_name = :Log
self.primary_key = :LogId
alias_attribute :log_id, :LogId
alias_attribute :job_id, :JobId
alias_attribute :time, :Time
alias_attribute :log_text, :LogText
belongs_to :job, foreign_key: :JobId
+ paginates_per 20
+
def time_formatted
if time
I18n.l(time, format: :long)
end
end
end
diff --git a/app/views/admin/clients/_recent_jobs.html.erb b/app/views/admin/clients/_recent_jobs.html.erb
index a444a8e..96514c6 100644
--- a/app/views/admin/clients/_recent_jobs.html.erb
+++ b/app/views/admin/clients/_recent_jobs.html.erb
@@ -1,22 +1,22 @@
Name |
JobId |
Level |
Fileset |
Started At |
Finished At |
Bytes |
Files |
Status |
- <%= render partial: 'recent_job', collection: @client.recent_jobs %>
+ <%= render partial: 'recent_job', collection: @jobs %>
diff --git a/app/views/admin/clients/jobs.html.erb b/app/views/admin/clients/jobs.html.erb
index f26a259..f8e83bc 100644
--- a/app/views/admin/clients/jobs.html.erb
+++ b/app/views/admin/clients/jobs.html.erb
@@ -1,10 +1,20 @@
<%= render partial: 'header' %>
-
Recent Jobs
+ Recent Jobs (<%= @jobs.total_count %>)
+
+
+
+ <%= page_entries_info @jobs, entry_name: 'job' %>
+
+
+ <%= paginate @jobs %>
+
+
+
<%= render partial: 'recent_jobs' %>
diff --git a/app/views/admin/clients/logs.html.erb b/app/views/admin/clients/logs.html.erb
index a87cdac..df7816c 100644
--- a/app/views/admin/clients/logs.html.erb
+++ b/app/views/admin/clients/logs.html.erb
@@ -1,25 +1,36 @@
<%= render partial: 'header' %>
-
Logs
+ Logs (<%= @logs.total_count %>)
+
+
+
+
+ <%= page_entries_info @logs, entry_name: 'log' %>
+
+
+ <%= paginate @logs %>
+
+
+
LogId |
Job |
Time |
Text |
<%= render partial: 'log', collection: @logs %>
diff --git a/app/views/clients/_recent_jobs.html.erb b/app/views/clients/_recent_jobs.html.erb
index d29f972..6a39c49 100644
--- a/app/views/clients/_recent_jobs.html.erb
+++ b/app/views/clients/_recent_jobs.html.erb
@@ -1,22 +1,22 @@
Name |
JobId |
Level |
Fileset |
Started At |
Finished At |
Bytes |
Files |
Status |
- <%= render partial: 'clients/recent_job', collection: @client.recent_jobs %>
+ <%= render partial: 'clients/recent_job', collection: @jobs %>
diff --git a/app/views/clients/jobs.html.erb b/app/views/clients/jobs.html.erb
index a22efeb..28b8c01 100644
--- a/app/views/clients/jobs.html.erb
+++ b/app/views/clients/jobs.html.erb
@@ -1,12 +1,20 @@
<%= render partial: 'header' %>
-
Recent Jobs
+ Recent Jobs (<%= @jobs.total_count %>)
+
+
+
+
+ <%= page_entries_info @jobs, entry_name: 'job' %>
+
+
+ <%= paginate @jobs %>
<%= render partial: 'recent_jobs' %>
<%= link_to 'Back to clients', clients_path %>
diff --git a/app/views/clients/logs.html.erb b/app/views/clients/logs.html.erb
index a87cdac..df7816c 100644
--- a/app/views/clients/logs.html.erb
+++ b/app/views/clients/logs.html.erb
@@ -1,25 +1,36 @@
<%= render partial: 'header' %>
-
Logs
+ Logs (<%= @logs.total_count %>)
+
+
+
+
+ <%= page_entries_info @logs, entry_name: 'log' %>
+
+
+ <%= paginate @logs %>
+
+
+
LogId |
Job |
Time |
Text |
<%= render partial: 'log', collection: @logs %>