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.
@@ -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,5 +1,6 @@
1
1
  class ActivitiesController < AuthorizedController
2
2
  belongs_to :project, :optional => true
3
+ belongs_to :person, :optional => true
3
4
 
4
5
  has_scope :by_date
5
6
 
@@ -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
@@ -1,24 +1,71 @@
1
1
  class WorkDay
2
- attr_accessor :date, :employment
2
+ attr_accessor :date, :employee
3
3
 
4
- def initialize(date, employment)
5
- @date = date
6
- @employment = employment
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
- employment.daily_workload
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
- employment.employee.activities.where(:date => date).to_a.sum(&:duration)
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
@@ -2,6 +2,3 @@
2
2
  %td= activity.person
3
3
  %td= link_to activity.date, activity, {'data-href-container' => 'tr'}
4
4
  %td= t('bookyt.projects.minutes', :duration => activity.duration)
5
- %td.action-links
6
- = list_link_for(:edit, activity, :remote => true)
7
- = list_link_for(:delete, activity)
@@ -2,6 +2,5 @@
2
2
  %tr
3
3
  - [:person, :date, :duration].each do |attr|
4
4
  %th= t_attr(attr, Activity)
5
- %th.action-links
6
5
 
7
6
  = render collection
@@ -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
- = f.input :name, :input_html => {'data-autofocus' => 'true'}
5
- = f.input :comment, :input_html => {:rows => 5}
6
- = f.input :duration_from, :as => :date_field
7
- = f.input :duration_to, :as => :date_field
8
- = f.input :project_state
9
- = f.input :client, :as => :combobox
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
- .form-view
2
- = render 'form'
1
+ %ul.tabs
2
+ %li.active= link_to 'Details', '#details'
3
+ %li= link_to 'Stundenrapport', '#activities'
3
4
 
4
- .contextual
5
- = icon_link_to :new, new_project_activity_path(resource)
6
- %h2= t_title :index, Activity
7
-
8
- = render 'activities/list', :collection => @project.activities
5
+ .tab-content
6
+ #details.active= render "form"
7
+ #activities= render 'show_activities'
@@ -0,0 +1,5 @@
1
+ .contextual
2
+ = icon_link_to :new, new_project_activity_path(resource)
3
+ %h2= t_title :index, Activity
4
+
5
+ = render 'activities/list', :collection => @project.activities
@@ -0,0 +1,3 @@
1
+ - activities.each do |activity|
2
+ %h4= "#{activity.project.name}: #{activity.duration}"
3
+ %p= activity.comment
@@ -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
- %h1= t_title
4
+ .page-header
5
+ %h1= t_title
5
6
 
6
- %table.list
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
@@ -9,4 +9,8 @@ Rails.application.routes.draw do
9
9
  resources :employees do
10
10
  resources :timesheets
11
11
  end
12
+
13
+ resources :people do
14
+ resources :activities
15
+ end
12
16
  end
@@ -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
@@ -1,3 +1,3 @@
1
1
  module BookytPos
2
- VERSION = '0.11.2'
2
+ VERSION = '0.12.0'
3
3
  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: 55
4
+ hash: 47
5
5
  prerelease:
6
6
  segments:
7
7
  - 0
8
- - 11
9
- - 2
10
- version: 0.11.2
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-13 00:00:00 Z
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.12
177
+ rubygems_version: 1.8.15
172
178
  signing_key:
173
179
  specification_version: 3
174
180
  summary: Project management plugin for bookyt