Compare commits

..

No commits in common. "213cc3127599d74aea1af5ba637182e39ee29818" and "a697bbf7beddd62b4c4faf1351e2b95e0855dd35" have entirely different histories.

15 changed files with 22 additions and 106 deletions

View File

@ -26,12 +26,10 @@ class JobsController < ApplicationController
end
def create
@job = Job.new(remove_empty_time_budgets(job_params))
if @job.save
if @job = Job.create(job_params)
redirect_to project_job_path(@job.project, @job)
else
@project = @job.project
render :new
render :edit
end
end

View File

@ -3,13 +3,10 @@ module JobsHelper
progress_bar(job.done_ratio,
legend: "#{job.done_ratio}%
(#{l_hours_short(job.total_time_logged)}/#{l_hours_short(job.total_time_budget)})",
class: "progress")
class: "progress")
end
def progress_bar_for(budget)
progress_bar(budget.done_ratio,
legend: "#{budget.done_ratio}%
(#{l_hours_short(budget.total_time_logged)}/#{l_hours_short(budget.hours)})",
class: "progress")
l_hours_short(budget.hours)
end
end

View File

@ -35,6 +35,12 @@ class Job < ActiveRecord::Base
time_budgets.sum(&:hours)
end
def time_budget_for(category)
return 0 if category.nil? || time_budgets.find_by(category_id: category.id).nil?
time_budgets.find_by(category_id: category.id).hours
end
def total_time_logged
TimeEntry.where(job_id: id)
.sum(:hours)
@ -50,27 +56,4 @@ class Job < ActiveRecord::Base
ActionView::Base.send(:include, Rails.application.routes.url_helpers)
ActionController::Base.helpers.link_to name, ActionController::Base.helpers.project_job_path(project, self)
end
def self.fields_for_order_statement
"jobs.name"
end
def self.default_for(time_entry)
projects = [time_entry.project, time_entry.project.parent]
jobs = Job.where(project: projects).active
support = jobs.where(category: JobCategory.support).first
retainer = jobs.where(category: JobCategory.retainer).first
sprints = jobs.where(category: JobCategory.sprints).first
priority_list = [sprints, retainer, support].compact
return jobs.first if priority_list.empty?
return support if time_entry.activity.name == "Support"
return priority_list.first if time_entry.issue.blank?
return support if time_entry.issue.tracker.name == "Support"
priority_list.first
end
end

View File

@ -5,10 +5,6 @@ class JobCategory < Enumeration
OptionName = :enumeration_job_category
scope :support, -> { where(name: 'Support').first }
scope :retainer, -> { where(name: 'Retainer').first }
scope :sprints, -> { where(name: 'Sprints').first }
def option_name
OptionName
end

View File

@ -10,18 +10,4 @@ class TimeBudget < ActiveRecord::Base
belongs_to :job
belongs_to :category, class_name: "TimeBudgetCategory"
def done_ratio
return 0 if hours.zero?
(total_time_logged / hours * 100).to_i
end
def total_time_logged
TimeEntry.joins(:user)
.where(
job_id: job_id,
users: { time_budget_category_id: category_id }
).sum(:hours)
end
end

View File

@ -24,7 +24,7 @@
<%= f.hidden_field :project_id, value: @job.project.id %>
<fieldset>
<legend>Budget (hours)</legend>
<legend>Budget</legend>
<%= f.fields_for :time_budgets do |ff| %>
<p>
<%= ff.label :hours, ff.object.category&.name || "Unassigned" %>

View File

@ -3,6 +3,10 @@
<td><%= job.category&.name || "Unassigned" %></td>
<td><%= format_date(job.starts_on) %></td>
<td><%= format_date(job.ends_on) %></td>
<td><%= job.project_id %></td>
<td>
<%= l_hours_short(job.total_time_budget) %>
</td>
<td>
<%= total_progress_bar(job) %>
</td>

View File

@ -15,6 +15,8 @@
<th>Category</th>
<th>Starts on</th>
<th>Ends on</th>
<th>Project</th>
<th>External project</th>
<th>Progress</th>
</tr>
</thead>

View File

@ -1,7 +1,3 @@
<% content_for :header_tags do %>
<%= stylesheet_link_tag "jobs", plugin: "jobs" %>
<% end %>
<% html_title @job.name %>
<div class="contextual">
<%= link_to 'Edit', edit_project_job_path(@project, @job), class: "icon icon-edit edit-job" %>
@ -11,7 +7,7 @@
<% end %>
</div>
<h2>Job #<%= @job.id %></h2>
<div class="job">
<div class="issue">
<div class="subject"><h3><%= @job.name %></h3></div>
<p><%= @job.description %></p>
<div class="attributes">
@ -23,7 +19,7 @@
<div class="label">Starts on:</div>
<div class="value"><%= format_date(@job.starts_on) %></div>
<div class="label">Ends on:</div>
<div class="value"><%= format_date(@job.ends_on) %></div>
<div class="value"><%= format_date(@job.starts_on) %></div>
</div>
</div>
<div class="splitcontentright">

View File

@ -1,3 +1,3 @@
<p>
<%= form.label :job_id %>
<%= form.collection_select :job_id, Job.active.project_or_parent(@project), :id, :name, include_blank: true %>
<%= form.collection_select :job_id, Job.project_or_parent(@project), :id, :name %>

View File

@ -1,16 +0,0 @@
/* These are a copy of the default CSS for issues */
div.job {background:#ffffdd; padding:6px; margin-bottom:6px; border: 1px solid #d7d7d7; border-radius:3px;}
div.job div.subject div div { padding-left: 16px; word-break: break-word; }
div.job div.subject p {margin: 0; margin-bottom: 0.1em; font-size: 90%; color: #999;}
div.job div.subject>div>p { margin-top: 0.5em; }
div.job div.subject h3 {margin: 0; margin-bottom: 0.1em;}
div.job p.author {margin-top:0.5em;}
div.job span.private, div.journal span.private {font-size: 60%;}
div.job .next-prev-links {color:#999;}
div.job .attributes {margin-top: 2em;}
div.job .attributes .attribute {padding-left:180px; clear:left; min-height: 1.8em;}
div.job .attributes .attribute .label {width: 170px; margin-left:-180px; font-weight:bold; float:left; overflow: clip visible; text-overflow: ellipsis;}
div.job .attribute .value {overflow:auto; text-overflow: ellipsis;}
div.job .attribute.string_cf .value .wiki p {margin-top: 0; margin-bottom: 0;}
div.job .attribute.text_cf .value .wiki p:first-of-type {margin-top: 0;}
div.job.overdue .due-date .value { color: #c22; }

View File

@ -1,5 +0,0 @@
class RemoveUniqueNameConstraintFromJobs < ActiveRecord::Migration[6.1]
def change
remove_index :jobs, :name
end
end

View File

@ -6,6 +6,7 @@ Redmine::Plugin.register :jobs do
url 'http://tsvallender.co.uk'
author_url 'http://tsvallender.co.uk'
permission :jobs, { jobs: [:index, :show, :new, :create, :edit, :update, :destroy] }, public: false
menu :project_menu, :jobs, { controller: 'jobs', action: 'index' }, caption: 'Jobs', after: :issues, param: :project_id
TimeEntry.safe_attributes 'job_id'
@ -17,8 +18,4 @@ Redmine::Plugin.register :jobs do
TimeEntry.send(:include, TimeEntryPatch)
Project.send(:include, ProjectPatch)
end
project_module :jobs do
permission :jobs, { jobs: [:index, :show, :new, :create, :edit, :update, :destroy] }, public: false
end
end

View File

@ -7,13 +7,5 @@ module TimeEntryPatch
included do
belongs_to :job
before_save :set_job, unless: :job
def set_job
return if job.present?
self.job = Job.default_for(self)
end
end
end

View File

@ -14,9 +14,6 @@ module TimeEntryQueryPatch
alias_method :available_columns_without_jobs, :available_columns
alias_method :available_columns, :available_columns_with_jobs
alias_method :joins_for_order_statement_without_jobs, :joins_for_order_statement
alias_method :joins_for_order_statement, :joins_for_order_statement_with_jobs
end
module InstanceMethods
@ -28,7 +25,7 @@ module TimeEntryQueryPatch
def available_columns_with_jobs
if @available_columns.nil?
@available_columns = available_columns_without_jobs
@available_columns << QueryColumn.new(:job, groupable: true, sortable: -> { Job.fields_for_order_statement })
@available_columns << QueryColumn.new(:job)
else
available_columns_without_jobs
end
@ -51,16 +48,5 @@ module TimeEntryQueryPatch
[job.name, job.id.to_s]
end
end
def joins_for_order_statement_with_jobs(order_options)
joins = joins_for_order_statement_without_jobs(order_options) || ""
if order_options
if order_options.include?('jobs')
joins += " LEFT OUTER JOIN #{Job.table_name} ON #{Job.table_name}.id = #{TimeEntry.table_name}.job_id"
end
end
joins
end
end
end