bookyt_projects 0.11.2 → 0.12.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/app/assets/stylesheets/bookyt_projects.sass +19 -1
- data/app/controllers/activities_controller.rb +1 -0
- data/app/controllers/timesheets_controller.rb +0 -4
- data/app/helpers/timesheet_helper.rb +28 -0
- data/app/models/work_day.rb +53 -6
- data/app/views/activities/_activity.html.haml +0 -3
- data/app/views/activities/_list.html.haml +0 -1
- data/app/views/people/_show_activities.html.haml +1 -0
- data/app/views/people/_show_timesheet.html.haml +1 -0
- data/app/views/projects/_form.html.haml +12 -6
- data/app/views/projects/_show.html.haml +6 -7
- data/app/views/projects/_show_activities.html.haml +5 -0
- data/app/views/timesheets/_activities_popover.html.haml +3 -0
- data/app/views/timesheets/_show.html.haml +20 -0
- data/app/views/timesheets/index.html.haml +3 -20
- data/config/locales/bookyt_projects.de.yml +5 -0
- data/config/routes.rb +4 -0
- data/lib/bookyt_projects/navigation.rb +3 -1
- data/lib/bookyt_projects/version.rb +1 -1
- metadata +12 -6
@@ -1,2 +1,20 @@
|
|
1
1
|
#overview-capture_hours
|
2
|
-
display: none
|
2
|
+
display: none
|
3
|
+
|
4
|
+
.strong
|
5
|
+
font-weight: bold
|
6
|
+
|
7
|
+
// Timesheets
|
8
|
+
tr
|
9
|
+
&.due_hours
|
10
|
+
background-color: #D1EED1 // block-message success
|
11
|
+
&.overtime
|
12
|
+
background-color: #DDF4FB // block-message info
|
13
|
+
&.undertime
|
14
|
+
background-color: #FDDFDE // block-message error
|
15
|
+
&.free, &.future
|
16
|
+
color: #BFBFBF // subtitle
|
17
|
+
|
18
|
+
tr.future
|
19
|
+
td.overtime, td.overall-overtime
|
20
|
+
color: transparent
|
@@ -1,9 +1,5 @@
|
|
1
1
|
class TimesheetsController < ApplicationController
|
2
2
|
def index
|
3
3
|
@employee = Employee.find(params[:employee_id])
|
4
|
-
@employment = @employee.employments.current
|
5
|
-
|
6
|
-
days = (Date.today.beginning_of_month..Date.today.end_of_month).to_a
|
7
|
-
@work_days = days.map{|day| WorkDay.new(day, @employment)}
|
8
4
|
end
|
9
5
|
end
|
@@ -0,0 +1,28 @@
|
|
1
|
+
module TimesheetHelper
|
2
|
+
# Calculate classes for WorkDay rows
|
3
|
+
#
|
4
|
+
# We add a 0.5h margin when determine over/undertime.
|
5
|
+
# Days in the future get the 'future' class.
|
6
|
+
def work_day_classes(day)
|
7
|
+
# No classes for days in the future
|
8
|
+
return 'future' if day.date > Date.today
|
9
|
+
|
10
|
+
classes = []
|
11
|
+
|
12
|
+
# TODO: make a setting
|
13
|
+
# +/- 0.5h is good
|
14
|
+
margin = 0.5
|
15
|
+
|
16
|
+
if day.overtime > margin
|
17
|
+
classes << 'overtime'
|
18
|
+
elsif day.overtime < -margin
|
19
|
+
classes << 'undertime'
|
20
|
+
elsif day.hours_due == 0.0
|
21
|
+
classes << 'free'
|
22
|
+
else
|
23
|
+
classes << 'due_hours'
|
24
|
+
end
|
25
|
+
|
26
|
+
classes.join(' ')
|
27
|
+
end
|
28
|
+
end
|
data/app/models/work_day.rb
CHANGED
@@ -1,24 +1,71 @@
|
|
1
1
|
class WorkDay
|
2
|
-
attr_accessor :date, :
|
2
|
+
attr_accessor :date, :employee
|
3
3
|
|
4
|
-
def initialize(
|
5
|
-
@date
|
6
|
-
@
|
4
|
+
def initialize(employee, date)
|
5
|
+
@date = date
|
6
|
+
@employee = employee
|
7
7
|
end
|
8
8
|
|
9
|
+
# Get WorkDay instances for a range
|
10
|
+
#
|
11
|
+
# Returns an array of WorkDay instances. You probably want
|
12
|
+
# to feed it a first day of month kind of starting_date.
|
13
|
+
#
|
14
|
+
# params:
|
15
|
+
# :employee: Employee to build WorkDay instances for
|
16
|
+
# :range: Date range giving first and last day
|
17
|
+
def self.for_range(employee, range)
|
18
|
+
range.to_a.map{|day| WorkDay.new(employee, day)}
|
19
|
+
end
|
20
|
+
|
21
|
+
# Get WorkDay instances for a month
|
22
|
+
#
|
23
|
+
# params:
|
24
|
+
# :employee: Employee to build WorkDay instances for
|
25
|
+
# :date_in_month: Any day in the requested month. Uses today by default.
|
26
|
+
def self.for_month(employee, date_in_month = nil)
|
27
|
+
# Assume today if no date given
|
28
|
+
date_in_month ||= Date.today
|
29
|
+
|
30
|
+
start_date = date_in_month.beginning_of_month
|
31
|
+
end_date = date_in_month.end_of_month
|
32
|
+
|
33
|
+
self.for_range(employee, start_date..end_date)
|
34
|
+
end
|
35
|
+
|
36
|
+
# Helper to access daily workload
|
37
|
+
#
|
38
|
+
# Returns 0.0 if no current daily_workload can be determined
|
39
|
+
def daily_workload
|
40
|
+
# Guard
|
41
|
+
return 0.0 unless employee && employee.employments.current && employee.employments.current.daily_workload
|
42
|
+
|
43
|
+
employee.employments.current.daily_workload
|
44
|
+
end
|
45
|
+
|
46
|
+
# Working hours for this day
|
9
47
|
def hours_due
|
10
48
|
case date.wday
|
11
49
|
when 6, 0
|
50
|
+
# Saturday and sunday are off
|
12
51
|
0.0
|
13
52
|
else
|
14
|
-
|
53
|
+
# Assume same working hours during the week
|
54
|
+
daily_workload
|
15
55
|
end
|
16
56
|
end
|
17
57
|
|
58
|
+
# Hours worked
|
59
|
+
#
|
60
|
+
# Calculates hours worked by summing up duration of all logged
|
61
|
+
# activities.
|
18
62
|
def hours_worked
|
19
|
-
|
63
|
+
employee.activities.where(:date => date).to_a.sum(&:duration)
|
20
64
|
end
|
21
65
|
|
66
|
+
# Overtime
|
67
|
+
#
|
68
|
+
# Simply substract hours_due from hours_worked.
|
22
69
|
def overtime
|
23
70
|
hours_worked - hours_due
|
24
71
|
end
|
@@ -0,0 +1 @@
|
|
1
|
+
= render 'activities/list', :collection => resource.activities
|
@@ -0,0 +1 @@
|
|
1
|
+
= render 'timesheets/show'
|
@@ -1,11 +1,17 @@
|
|
1
1
|
= semantic_form_for @project do |f|
|
2
2
|
= f.semantic_errors
|
3
3
|
= f.inputs do
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
4
|
+
.row
|
5
|
+
.span8
|
6
|
+
= f.input :name, :input_html => {'data-autofocus' => 'true'}
|
7
|
+
= f.input :duration_from, :as => :date_field
|
8
|
+
= f.input :client, :as => :combobox
|
9
|
+
.span8
|
10
|
+
= f.input :project_state
|
11
|
+
= f.input :duration_to, :as => :date_field
|
12
|
+
.row
|
13
|
+
.span16
|
14
|
+
= f.input :comment, :input_html => {:rows => 5, :class => 'span12'}
|
15
|
+
|
10
16
|
= f.buttons do
|
11
17
|
= f.commit_button
|
@@ -1,8 +1,7 @@
|
|
1
|
-
.
|
2
|
-
=
|
1
|
+
%ul.tabs
|
2
|
+
%li.active= link_to 'Details', '#details'
|
3
|
+
%li= link_to 'Stundenrapport', '#activities'
|
3
4
|
|
4
|
-
.
|
5
|
-
=
|
6
|
-
|
7
|
-
|
8
|
-
= render 'activities/list', :collection => @project.activities
|
5
|
+
.tab-content
|
6
|
+
#details.active= render "form"
|
7
|
+
#activities= render 'show_activities'
|
@@ -0,0 +1,20 @@
|
|
1
|
+
%table.condensed-table.span8
|
2
|
+
%tr
|
3
|
+
%th= t_attr :date, Activity
|
4
|
+
%th.number= t_attr :working_hours, Activity
|
5
|
+
%th.number= t_attr :overtime, Activity
|
6
|
+
%th.number= t_attr :overall_overtime, Activity
|
7
|
+
|
8
|
+
- overall_overtime = 0
|
9
|
+
- WorkDay.for_month(@employee).each do |day|
|
10
|
+
- overall_overtime += day.overtime
|
11
|
+
- activities = @employee.activities.where(:date => day.date)
|
12
|
+
- tr_params = {:class => work_day_classes(day)}
|
13
|
+
- tr_params.merge!(:rel => 'popover', 'data-content' => h(render 'activities_popover', :activities => activities), 'data-original-title' => 'Aktivitäten', 'data-html' => 'true') unless activities.empty?
|
14
|
+
%tr{tr_params}
|
15
|
+
%td= link_to l(day.date, :format => '%a, %d.%m.%Y'), person_activities_path(@employee, :by_date => day.date.to_s(:db)), 'data-href-container' => 'tr'
|
16
|
+
%td.number
|
17
|
+
%span.strong= "%0.1f" % day.hours_worked
|
18
|
+
= "(%0.1f)" % day.hours_due
|
19
|
+
%td.number.overtime.strong= day.overtime
|
20
|
+
%td.number.overall-overtime.strong= overall_overtime
|
@@ -1,24 +1,7 @@
|
|
1
1
|
.contextual
|
2
2
|
= contextual_link_to :new, Activity
|
3
3
|
|
4
|
-
|
4
|
+
.page-header
|
5
|
+
%h1= t_title
|
5
6
|
|
6
|
-
|
7
|
-
%tr
|
8
|
-
%th= t_attr :date, Activity
|
9
|
-
%th Wochentag
|
10
|
-
%th.number= t_attr :hours_due, Activity
|
11
|
-
%th.number= t_attr :hours_worked, Activity
|
12
|
-
%th.number= t_attr :overtime, Activity
|
13
|
-
%th.number= t_attr :overall_overtime, Activity
|
14
|
-
|
15
|
-
- overall_overtime = 0
|
16
|
-
- @work_days.each do |day|
|
17
|
-
- overall_overtime += day.overtime
|
18
|
-
%tr
|
19
|
-
%td= day.date
|
20
|
-
%td= l(day.date, :format => '%A')
|
21
|
-
%td.number= day.hours_due
|
22
|
-
%td.number= day.hours_worked
|
23
|
-
%td.number= day.overtime
|
24
|
-
%td.number= overall_overtime
|
7
|
+
= render 'show'
|
@@ -33,6 +33,7 @@ de:
|
|
33
33
|
time: Zeitraum
|
34
34
|
hours_due: Soll-Stunden
|
35
35
|
hours_worked: Arbeitsstunden
|
36
|
+
working_hours: Stunden (Soll)
|
36
37
|
overtime: Über-/Unterzeit
|
37
38
|
overall_overtime: Saldo
|
38
39
|
|
@@ -51,3 +52,7 @@ de:
|
|
51
52
|
activities:
|
52
53
|
new:
|
53
54
|
title: Zeit erfassen
|
55
|
+
list:
|
56
|
+
title: Aktivitäten
|
57
|
+
timesheet:
|
58
|
+
title: Stundenrapport
|
data/config/routes.rb
CHANGED
@@ -2,9 +2,11 @@ module BookytProjects
|
|
2
2
|
module Navigation
|
3
3
|
def setup_bookyt_projects(navigation)
|
4
4
|
navigation.item :projects, t('bookyt.main_navigation.projects'), projects_path, :if => Proc.new { user_signed_in? } do |projects|
|
5
|
-
projects.item :capture_hours, t('activities.new.title'), new_batch_activity_path
|
6
5
|
projects.item :project_index, t_title(:index, Project), projects_path, :highlights_on => /\/(projects|activities)($|\/[0-9]*($|\/.*))/
|
7
6
|
projects.item :new_project, t_title(:new, Project), new_project_path
|
7
|
+
projects.item :divider, "", :class => 'divider'
|
8
|
+
projects.item :capture_hours, t('activities.new.title'), new_batch_activity_path
|
9
|
+
projects.item :divider, "", :class => 'divider'
|
8
10
|
projects.item :project_states, t_model(ProjectState), project_states_path, :highlights_on => /\/project_states($|\/([0-9]*|new)($|\/.*))/
|
9
11
|
end
|
10
12
|
end
|
metadata
CHANGED
@@ -1,13 +1,13 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: bookyt_projects
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
hash:
|
4
|
+
hash: 47
|
5
5
|
prerelease:
|
6
6
|
segments:
|
7
7
|
- 0
|
8
|
-
-
|
9
|
-
-
|
10
|
-
version: 0.
|
8
|
+
- 12
|
9
|
+
- 0
|
10
|
+
version: 0.12.0
|
11
11
|
platform: ruby
|
12
12
|
authors:
|
13
13
|
- Roman Simecek (CyT)
|
@@ -16,7 +16,7 @@ autorequire:
|
|
16
16
|
bindir: bin
|
17
17
|
cert_chain: []
|
18
18
|
|
19
|
-
date: 2012-01-
|
19
|
+
date: 2012-01-16 00:00:00 Z
|
20
20
|
dependencies:
|
21
21
|
- !ruby/object:Gem::Dependency
|
22
22
|
name: rails
|
@@ -108,6 +108,7 @@ files:
|
|
108
108
|
- app/controllers/project_states_controller.rb
|
109
109
|
- app/controllers/projects_controller.rb
|
110
110
|
- app/controllers/timesheets_controller.rb
|
111
|
+
- app/helpers/timesheet_helper.rb
|
111
112
|
- app/models/activity.rb
|
112
113
|
- app/models/bookyt_projects/person.rb
|
113
114
|
- app/models/project.rb
|
@@ -118,11 +119,16 @@ files:
|
|
118
119
|
- app/views/activities/_list.html.haml
|
119
120
|
- app/views/batch_activities/_form.html.haml
|
120
121
|
- app/views/batch_activities/new.html.haml
|
122
|
+
- app/views/people/_show_activities.html.haml
|
123
|
+
- app/views/people/_show_timesheet.html.haml
|
121
124
|
- app/views/project_states/_form.html.haml
|
122
125
|
- app/views/projects/_form.html.haml
|
123
126
|
- app/views/projects/_list.html.haml
|
124
127
|
- app/views/projects/_project.html.haml
|
125
128
|
- app/views/projects/_show.html.haml
|
129
|
+
- app/views/projects/_show_activities.html.haml
|
130
|
+
- app/views/timesheets/_activities_popover.html.haml
|
131
|
+
- app/views/timesheets/_show.html.haml
|
126
132
|
- app/views/timesheets/index.html.haml
|
127
133
|
- config/application.rb
|
128
134
|
- config/boot.rb
|
@@ -168,7 +174,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
168
174
|
requirements: []
|
169
175
|
|
170
176
|
rubyforge_project:
|
171
|
-
rubygems_version: 1.8.
|
177
|
+
rubygems_version: 1.8.15
|
172
178
|
signing_key:
|
173
179
|
specification_version: 3
|
174
180
|
summary: Project management plugin for bookyt
|