diff --git a/app/controllers/admin/clients_controller.rb b/app/controllers/admin/clients_controller.rb new file mode 100644 index 0000000..9d8ce6e --- /dev/null +++ b/app/controllers/admin/clients_controller.rb @@ -0,0 +1,38 @@ +class Admin::ClientsController < Admin::BaseController + before_action :fetch_client, only: [:show] + + # 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 + @client_ids = [@client.id] + get_logs + get_charts + end + + private + + # Fetches the client based on the given id + def fetch_client + @client = Client.find(params[: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/views/admin/clients/_client.html.erb b/app/views/admin/clients/_client.html.erb new file mode 100644 index 0000000..bfc21bf --- /dev/null +++ b/app/views/admin/clients/_client.html.erb @@ -0,0 +1,12 @@ + + <%= link_to "##{client.id}", admin_client_path(client) %> + <%= link_to client.name, admin_client_path(client) %> + <%= client.uname %> + <%= @stats.active_jobs[client.id] || 0 %> + <%= @stats.last_jobs[client.id] %> + <%= client.file_retention_days %> + <%= client.job_retention_days %> + <%= number_to_human_size(@stats.jobs_sizes[client.id]) %> + <%= number_by_magnitude(@stats.jobs_files[client.id]) %> + <%= client.auto_prune_human %> + diff --git a/app/views/admin/clients/_client_details.html.erb b/app/views/admin/clients/_client_details.html.erb new file mode 100644 index 0000000..161b7bd --- /dev/null +++ b/app/views/admin/clients/_client_details.html.erb @@ -0,0 +1,44 @@ +
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Name<%= @client.name %>
Uname<%= @client.uname %>
Active Jobs<%= @client.running_jobs %>
Last Backup + <%= @client.last_job_date_formatted %> +
File Retention<%= @client.file_retention_days %> days
Job Retention<%= @client.job_retention_days %> days
Total Space Used<%= number_to_human_size @client.backup_jobs_size %>
Files count<%= number_by_magnitude(@client.files_count) %>
Auto Prune<%= @client.auto_prune_human %>
+
+
diff --git a/app/views/admin/clients/_client_graphs.html.erb b/app/views/admin/clients/_client_graphs.html.erb new file mode 100644 index 0000000..0d1a682 --- /dev/null +++ b/app/views/admin/clients/_client_graphs.html.erb @@ -0,0 +1,18 @@ +
+
+
+
+
+
+
+
+
+ <%= bootstrap_form_tag(url: path, method: :get, layout: :inline) do |f| %> + <%= f.select(:days_back, [['1 week', 7], ['2 weeks', 14], ['1 month', 30]]) %> + <%= f.submit 'See Stats', class: "btn btn-primary" %> + <% end %> +
+
+ +<%= baas_chart('jobs_status', @job_status) %> +<%= baas_chart('jobs_stats', @job_stats) %> diff --git a/app/views/admin/clients/_job.html.erb b/app/views/admin/clients/_job.html.erb new file mode 100644 index 0000000..f10eda8 --- /dev/null +++ b/app/views/admin/clients/_job.html.erb @@ -0,0 +1,7 @@ + + <%= job.name %> + <%= job.job_type %> + <%= job.fileset.try(:name) %> + <%= job.schedule_human %> + <%= I18n.l(job.created_at, format: :long) %> + diff --git a/app/views/admin/clients/_jobs.html.erb b/app/views/admin/clients/_jobs.html.erb new file mode 100644 index 0000000..d7a4d0f --- /dev/null +++ b/app/views/admin/clients/_jobs.html.erb @@ -0,0 +1,18 @@ +
+
+ + + + + + + + + + + + <%= render partial: 'job', collection: @client.persisted_jobs, object: :job %> + +
NameTypeFilesetScheduleCreated
+
+
diff --git a/app/views/admin/clients/_log.html.erb b/app/views/admin/clients/_log.html.erb new file mode 100644 index 0000000..589a415 --- /dev/null +++ b/app/views/admin/clients/_log.html.erb @@ -0,0 +1,8 @@ + + <%= log.log_id %> + <%= log.job.name %> + <%= log.time_formatted %> +
+<%= log.log_text %>
+  
+ diff --git a/app/views/admin/clients/_logs.html.erb b/app/views/admin/clients/_logs.html.erb new file mode 100644 index 0000000..adcfe45 --- /dev/null +++ b/app/views/admin/clients/_logs.html.erb @@ -0,0 +1,23 @@ +
+
+

Logs

+
+ +
+
+ + + + + + + + + + + <%= render partial: 'log', collection: @logs %> + +
LogIdJobTimeText
+
+
+
diff --git a/app/views/admin/clients/_recent_job.html.erb b/app/views/admin/clients/_recent_job.html.erb new file mode 100644 index 0000000..109626b --- /dev/null +++ b/app/views/admin/clients/_recent_job.html.erb @@ -0,0 +1,11 @@ + + <%= recent_job.name %> + <%= recent_job.job_id %> + <%= recent_job.level_human %> + <%= recent_job.fileset %> + <%= recent_job.start_time_formatted %> + <%= recent_job.end_time_formatted %> + <%= number_to_human_size(recent_job.job_bytes) %> + <%= number_by_magnitude(recent_job.job_files) %> + <%= recent_job.status_human %> + diff --git a/app/views/admin/clients/_recent_jobs.html.erb b/app/views/admin/clients/_recent_jobs.html.erb new file mode 100644 index 0000000..a444a8e --- /dev/null +++ b/app/views/admin/clients/_recent_jobs.html.erb @@ -0,0 +1,22 @@ +
+
+ + + + + + + + + + + + + + + + <%= render partial: 'recent_job', collection: @client.recent_jobs %> + +
NameJobIdLevelFilesetStarted AtFinished AtBytesFilesStatus
+
+
diff --git a/app/views/admin/clients/index.html.erb b/app/views/admin/clients/index.html.erb new file mode 100644 index 0000000..98e580f --- /dev/null +++ b/app/views/admin/clients/index.html.erb @@ -0,0 +1,24 @@ +

Bacula Clients

+ +
+ + + + + + + + + + + + + + + + + + <%= render partial: 'client', collection: @clients %> + +
ClientIdNameUnameActive JobsLast BackupFileRetention (days)JobRetention (days)Space UsedFile countAutoPrune
+
diff --git a/app/views/admin/clients/show.html.erb b/app/views/admin/clients/show.html.erb new file mode 100644 index 0000000..f30a0c7 --- /dev/null +++ b/app/views/admin/clients/show.html.erb @@ -0,0 +1,44 @@ +

<%= notice %>

+<% if @client.host %> +
+ <%= link_to 'Manage Client', 'admin_host_path(@client.host)', class: "btn btn-primary", role: "button" %> +
+<% end %> + +

<%= @client.name %>

+ +
+
+

Client Details

+
+
+

Bacula Jobs

+
+
+ +
+ <%= render partial: 'client_details' %> +
+
+ <% if @client.host %> + <%= render partial: 'jobs' %> + <% end %> +
+
+
+

Recent Jobs

+
+
+
+ <%= render partial: 'recent_jobs' %> +
+
+
+ +
+ +<%= render partial: 'client_graphs', locals: { path: admin_client_path(@client) } %> + +
+ +<%= render partial: 'logs' %> diff --git a/app/views/shared/_nav.html.erb b/app/views/shared/_nav.html.erb index fefa4ff..654d8cc 100644 --- a/app/views/shared/_nav.html.erb +++ b/app/views/shared/_nav.html.erb @@ -1,34 +1,35 @@ diff --git a/config/routes.rb b/config/routes.rb index d8f978d..d2fd087 100644 --- a/config/routes.rb +++ b/config/routes.rb @@ -1,28 +1,30 @@ Rails.application.routes.draw do root 'clients#index' resources :clients, only: [:index, :show] resources :hosts, only: [:new, :create, :show, :edit, :update, :destroy] do member do post :submit_config get :restore post :run_restore delete :revoke end resources :jobs, only: [:new, :create, :show, :edit, :update, :destroy] do member do patch :toggle_enable post :backup_now end end resources :filesets, only: [:show, :new, :create, :destroy] resources :schedules, only: [:show, :new, :edit, :create, :update, :destroy] end namespace :admin do get '/' => 'base#index' + + resources :clients, only: [:index, :show] end end