Initial commit

This commit is contained in:
Trevor Vallender 2023-11-16 20:23:09 +00:00
commit dbeaf3973d
18 changed files with 258 additions and 0 deletions

6
README.rdoc Normal file
View File

@ -0,0 +1,6 @@
= Jobs
_Jobs_ is a Redmine plugin allowing the management of jobs—chunks of time sold to clients for budget management.
- Add jobs with time budgets
- Associated time log entries with a given job

View File

@ -0,0 +1,64 @@
class JobsController < ApplicationController
before_action :set_project, only: [:index, :new, :show, :edit]
before_action :set_job, only: [:show, :edit, :update, :destroy]
def index
@jobs = Job.all
end
def show
end
def new
@job = Job.new
end
def edit
end
def update
if @job.update(job_params)
redirect_to @job
else
render :edit
end
end
def create
if @job = Job.create(job_params)
redirect_to @job
else
render :edit
end
end
def destroy
if @job.destroy
redirect_to jobs_path(project_id: @project.id)
else
render :show
end
end
private
def job_params
params.require(:job).permit(
:starts_on,
:ends_on,
:project_id,
:budget,
:external_project_id,
:name,
:description
)
end
def set_project
@project = Project.find(params[:project_id])
end
def set_job
@job = Job.find(params[:id])
end
end

View File

@ -0,0 +1,2 @@
module JobsHelper
end

10
app/models/job.rb Normal file
View File

@ -0,0 +1,10 @@
class Job < ActiveRecord::Base
validates :starts_on,
:ends_on,
:name,
presence: true
def time_logged
42
end
end

View File

@ -0,0 +1,40 @@
<div class="box tabular">
<%= form_with model: @job, id: "job_form" do |f| %>
<p>
<%= f.label :name %>
<%= f.text_field :name %>
</p>
<p>
<%= f.label :description %>
<%= f.text_area :description %>
</p>
<p>
<%= f.label :starts_on %>
<%= f.date_field :starts_on %>
</p>
<p>
<%= f.label :ends_on %>
<%= f.date_field :ends_on %>
</p>
<p>
<%= f.label :project_id %>
<%= f.number_field :project_id %>
</p>
<p>
<%= f.label :external_project_id %>
<%= f.number_field :external_project_id %>
</p>
<p>
<%= f.label :budget %>
<%= f.number_field :budget %>
</p>
<%= f.submit %>
<% end %>
</div>

View File

@ -0,0 +1,9 @@
<tr>
<td><%= link_to job.name, job_path(job, project_id: job.project_id) %></td>
<td><%= job.starts_on %></td>
<td><%= job.ends_on %></td>
<td><%= job.project_id %></td>
<td><%= job.external_project_id %></td>
<td><%= job.budget %></td>
</tr>

View File

@ -0,0 +1,6 @@
<% html_title "Edit #{@job.name}" %>
<h2>Edit <%= @job.name %></h2>
<%= render "form" %>
<%= link_to "Delete job", job_path(@job), data: { confirm: "Are you sure?" }, method: :delete %>

View File

@ -0,0 +1,26 @@
<% html_title "Jobs" %>
<div class="contextual">
<%= link_to 'Create new job', new_job_path(project_id: @project.id), class: "icon icon-add new-job" %>
</div>
<h2>Jobs</h2>
<% if @jobs.empty? %>
<p>You havent created any jobs yet.</p>
<% else %>
<table class="list">
<thead>
<tr>
<th>Name</th>
<th>Starts on</th>
<th>Ends on</th>
<th>Project</th>
<th>External project</th>
<th>Budget</th>
</tr>
</thead>
<tbody>
<%= render @jobs %>
</tbody>
</table>
<% end %>

View File

@ -0,0 +1,3 @@
<h2><%= link_to "Jobs", jobs_path(project_id: @project.id) %> » New</h2>
<%= render "form" %>

View File

@ -0,0 +1,11 @@
<% html_title @job.name %>
<h3><%= link_to @job.name, @job %></h3>
<p><%= @job.description %></p>
<dl>
<dt>Starts on:</dt>
<dd><%= @job.starts_on %></dd>
<dt>Ends on:</dt>
<dd><%= @job.ends_on %></dd>
</dl>
<%= link_to 'Edit job', edit_job_path(@job, project_id: @project.id) %>

3
config/locales/en.yml Normal file
View File

@ -0,0 +1,3 @@
# English strings go here for Rails i18n
en:
# my_label: "My label"

1
config/routes.rb Normal file
View File

@ -0,0 +1 @@
resources :jobs

View File

@ -0,0 +1,14 @@
class CreateJobs < ActiveRecord::Migration[6.1]
def change
create_table :jobs do |t|
t.date :starts_on, null: false
t.date :ends_on, null: false
t.integer :external_project_id
t.string :name, null: false
t.references :project, foreign_key: true
t.string :description
t.integer :budget
end
add_index :jobs, :name, unique: true
end
end

11
init.rb Normal file
View File

@ -0,0 +1,11 @@
Redmine::Plugin.register :jobs do
name 'Redmine Jobs plugin'
author 'T S Vallender'
description 'Manage jobs in Redmine'
version '0.0.1'
url 'http://tsvallender.co.uk'
author_url 'http://tsvallender.co.uk'
permission :jobs, { jobs: [:index, :show, :new, :create, :edit, :update, :destroy] }, public: true
menu :project_menu, :jobs, { controller: 'jobs', action: 'index' }, caption: 'Jobs', after: :issues, param: :project_id
end

View File

@ -0,0 +1,8 @@
require_relative '../test_helper'
class JobsControllerTest < ActionController::TestCase
# Replace this with your real tests.
def test_truth
assert true
end
end

2
test/test_helper.rb Normal file
View File

@ -0,0 +1,2 @@
# Load the Redmine helper
require_relative '../../../test/test_helper'

9
test/unit/job_test.rb Normal file
View File

@ -0,0 +1,9 @@
require_relative '../test_helper'
class JobTest < ActiveSupport::TestCase
# Replace this with your real tests.
def test_truth
assert true
end
end

33
todo.md Normal file
View File

@ -0,0 +1,33 @@
- Add a job model
- Start/end date
- External project ID (one-to-one relationship)
- Name
- Client (project ID)
- Description
- Job ID? (this is in Amigo)
- Status (pending acceptance etc.)
- Total time (budget per activity type?)
- List of associated trackers
- Add association between time log entries and jobs
- Add UI for jobs
- CRUD stuff
- Set up default associations
- Separate plugin:
- Whenever time log is updated, fire this at Everhour
- Back the other way?
- What about meetings etc?
- Examples:
- Developer logs time for ticket #123
- Doesn't explicitly choose a job
- Logged as development time
- If ticket is in retainer tracker the time is logged against the retainer job
- If ticket is in support tracker the time is logged against the support job
- If ticket is anywhere else, it is logged against the active project
- Product manager logs time for ticket #123
- Doesn't explicitly choose a job
- Logged as refinement time
-