devlog 0.3.2 → 0.3.5

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.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
- SHA1:
3
- metadata.gz: 2712d58a9f98c77851b3453e22dd929f4aa7eae6
4
- data.tar.gz: 30bfd02ebd5ad88eeef83084c15850b618bcaf21
2
+ SHA256:
3
+ metadata.gz: b1a45392960ca81bf6302d673596bf04eccd7a070b66cb51b23e9ba692b9ccac
4
+ data.tar.gz: d641ca12c1ecf98e909162c47b6ff4a62c7d75f917cfc9c78a061ce06b3bad28
5
5
  SHA512:
6
- metadata.gz: d3d76b2d648cdee3327ffcfdbca596a287bc38dc203800c3958f9121946daf7ee8bc39e7abc0a74e56009010ec8e512e08e1249725c6f3b590a4b60e632a6055
7
- data.tar.gz: 47e76d5297ebaeaeed0e130c9cc3b0a9426522d02565d620a248e7a3abbc7821f21a4b0dfcf49c06d6a2c41fe0aeaf68c3bcd18c6723642e63116ef825b3fec5
6
+ metadata.gz: 2cf0628f73115547749bb7154aa7fc5711b87503afcb50109aef5905450b2fe25d09093f9fb4eab235bf58c2d5d0348ea6f2882389c16d37f79c7761282f90bb
7
+ data.tar.gz: 0e6be9b4a306be177a7234594c71c19962ea343773aec4ef5bd5fee04a3db4f18e9c7cb4c64278fa81a57c7e52d3058b3ae87750d1734d3e1ba284ebb3bcf0ee
@@ -0,0 +1,28 @@
1
+ name: devlog CI
2
+
3
+ on:
4
+ push:
5
+ branches: [ main ]
6
+ pull_request:
7
+ branches: [ main ]
8
+
9
+ jobs:
10
+ test:
11
+
12
+ runs-on: ubuntu-latest
13
+
14
+ strategy:
15
+ matrix:
16
+ ruby-version: [3.0.1, 2.7.3]
17
+ os: [ubuntu-latest, macOS-lates]
18
+
19
+ steps:
20
+ - uses: actions/checkout@v2
21
+ - name: Set up Ruby ${{ runner.os }}-§${{ matrix.ruby-version }}
22
+ uses: ruby/setup-ruby@477b21f02be01bcb8030d50f37cfec92bfa615b6
23
+ with:
24
+ ruby-version: ${{ matrix.ruby-version }}
25
+ - name: Install dependencies
26
+ run: bundle install
27
+ - name: Run tests
28
+ run: bundle exec rake
data/.ruby-version CHANGED
@@ -1,3 +1 @@
1
- 2.3.0
2
-
3
-
1
+ 3.0.1
data/README.md CHANGED
@@ -28,15 +28,14 @@ like a book, top down, but always start a new session on top of the file, so tha
28
28
  devlog DSL
29
29
  ==========
30
30
 
31
+ #DD.MM.YYYY HH:MM:SS CodingSession::END
31
32
 
32
- #DD.MM.YYYY HH:MM:SS CodingSession::END
33
+ devlog text...
33
34
 
34
- devlog text...
35
+ #DD.MM.YYYY HH:MM:SS CodingSession::BEGIN
35
36
 
36
- #DD.MM.YYYY HH:MM:SS CodingSession::BEGIN
37
-
38
- using the devlog binary
39
- ===================
37
+ using the devlog CLI
38
+ ====================
40
39
 
41
40
  to parse a devlog file explicitly:
42
41
 
@@ -76,19 +75,33 @@ run in current folder and write out info.markdown, copy devlog to README.markdow
76
75
 
77
76
  `devlog saver`
78
77
 
78
+ write out a weekly timesheet for the current week, using a ERB template producing html + PDF:
79
+
80
+ `devlog w`
81
+
82
+ writing out the week before the current one (and so on):
83
+
84
+ `devlog w 1`
85
+
79
86
  settings
80
87
  ========
81
88
 
82
- currently only `devlog_file` can be configured. it represents the location of the devlog text file.
83
-
84
89
  the settings file is called `.devlog.yml`.
85
90
 
86
91
  it can be placed into a project folder from where one wants to be able to call `devlog`.
87
92
 
93
+ this way you can keep your devlog.markdown anywhere on disk.
94
+
95
+ `devlog_file` represents the location of the devlog text file.
96
+ `weekly_timesheet_template` represents the location of the ERB weekly timesheet template, if you don't provide one, there's a default.
97
+ `convert_to_pdf_command` represents the command used to convert the generated html into a signable PDF.
98
+
99
+ file paths should be relative to `.devlog.yml`.
100
+
88
101
  example settings `.devlog.yml`:
89
102
 
90
103
  ```
91
104
  devlog_file: ../info/devlog.markdown
105
+ weekly_timesheet_template: ../info/weekly_timesheet.erb.html
106
+ convert_to_pdf_command: wkhtmltopdf --dpi 400 --viewport-size 600x800 --orientation Landscape
92
107
  ```
93
-
94
- the file path should be relative to `.devlog.yml`.
data/VERSION CHANGED
@@ -1 +1 @@
1
- 0.3.2
1
+ 0.3.5
data/bin/devlog CHANGED
@@ -31,11 +31,15 @@ exporting devlog into a book, which can be read top down, like normal books:
31
31
 
32
32
  #{'devlog'.green} x ~ exports into devlog.txt
33
33
 
34
+ reporting devlog as a timesheet:
35
+
36
+ #{'devlog'.green} w ~ export the current weekly timesheet into a html page and convert that into PDF
34
37
  EOF
35
38
 
36
39
  # arguments
37
40
  $:.unshift File.join(File.dirname(__FILE__))
38
41
  @in_file_or_cmd = ARGV[0]
42
+ @argument = ARGV[1] ? ARGV[1].to_i : 0
39
43
 
40
44
  def print_backtrace(exception)
41
45
  exception.backtrace.join("\n\t").to_s.blue
@@ -51,6 +55,7 @@ def parse_now(devlog_file = 'devlog.markdown', msg = '')
51
55
  puts t.validation_string
52
56
  puts t.to_info_string
53
57
  puts is_session_open(devlog_file) ? "\nSession is open...".yellow : "\nNo open session.".green
58
+ t
54
59
  end
55
60
 
56
61
  def export_now(devlog_file = 'devlog.markdown', msg = '')
@@ -63,6 +68,7 @@ include Devlog
63
68
 
64
69
  def dodo
65
70
  load_settings('.devlog.yml')
71
+ ENV['TZ'] = devlog_timezone_setting
66
72
  default_devlog_file = devlog_file_setting
67
73
  time = Benchmark.realtime do
68
74
  if @in_file_or_cmd =~ /.(markdown|md)$/ # devlog_file is passed directly via CLI
@@ -72,6 +78,8 @@ def dodo
72
78
  print_usage
73
79
  elsif @in_file_or_cmd == 'x'
74
80
  export_now(default_devlog_file, "Exporting #{default_devlog_file}...".green)
81
+ elsif @in_file_or_cmd == 'w'
82
+ weekly_pdf(parse_now(default_devlog_file, "Parsing #{default_devlog_file}...".green), @argument)
75
83
  elsif @in_file_or_cmd == 'commit'
76
84
  `git commit -am 'devlog';git push`
77
85
  elsif @in_file_or_cmd == 'b'
data/devlog.gemspec CHANGED
@@ -2,16 +2,16 @@
2
2
  # DO NOT EDIT THIS FILE DIRECTLY
3
3
  # Instead, edit Jeweler::Tasks in Rakefile, and run 'rake gemspec'
4
4
  # -*- encoding: utf-8 -*-
5
- # stub: devlog 0.3.2 ruby lib
5
+ # stub: devlog 0.3.5 ruby lib
6
6
 
7
7
  Gem::Specification.new do |s|
8
8
  s.name = "devlog".freeze
9
- s.version = "0.3.2"
9
+ s.version = "0.3.5"
10
10
 
11
11
  s.required_rubygems_version = Gem::Requirement.new(">= 0".freeze) if s.respond_to? :required_rubygems_version=
12
12
  s.require_paths = ["lib".freeze]
13
13
  s.authors = ["mihael".freeze]
14
- s.date = "2018-06-01"
14
+ s.date = "2023-09-25"
15
15
  s.description = "devlog.markdown time&space extractor".freeze
16
16
  s.email = "kitschmaster@gmail.com".freeze
17
17
  s.executables = ["devlog".freeze]
@@ -20,9 +20,9 @@ Gem::Specification.new do |s|
20
20
  "README.md"
21
21
  ]
22
22
  s.files = [
23
+ ".github/workflows/devlog_test.yml",
23
24
  ".ruby-gemset",
24
25
  ".ruby-version",
25
- ".travis.yml",
26
26
  "Gemfile",
27
27
  "LICENSE",
28
28
  "README.md",
@@ -43,6 +43,8 @@ Gem::Specification.new do |s|
43
43
  "sublime_text/devlog.tmbundle/Snippets/tu.tmSnippet",
44
44
  "sublime_text/devlog.tmbundle/info.plist",
45
45
  "sublime_text/tu.py",
46
+ "templates/background.jpg",
47
+ "templates/weekly_timesheet.erb.html",
46
48
  "test/devlog_file_test.rb",
47
49
  "test/devlog_settings_test.rb",
48
50
  "test/devlog_test.rb",
@@ -56,28 +58,24 @@ Gem::Specification.new do |s|
56
58
  "test/test_devlogs/test_settings.yml",
57
59
  "test/test_devlogs/test_single_devlog.markdown",
58
60
  "test/test_devlogs/test_stats_devlog.markdown",
61
+ "test/test_devlogs/test_weekly_devlog.markdown",
59
62
  "test/test_helper.rb",
60
63
  "tmp/.gitignore"
61
64
  ]
62
65
  s.homepage = "http://github.com/mihael/devlog".freeze
63
66
  s.licenses = ["MIT".freeze]
64
- s.rubygems_version = "2.5.2".freeze
67
+ s.rubygems_version = "3.2.15".freeze
65
68
  s.summary = "takes devlog.markdown and gives info".freeze
66
69
 
67
70
  if s.respond_to? :specification_version then
68
71
  s.specification_version = 4
72
+ end
69
73
 
70
- if Gem::Version.new(Gem::VERSION) >= Gem::Version.new('1.2.0') then
71
- s.add_runtime_dependency(%q<activesupport>.freeze, ["> 4.1"])
72
- s.add_development_dependency(%q<test-unit>.freeze, ["~> 3.1"])
73
- s.add_development_dependency(%q<jeweler>.freeze, ["~> 2.0"])
74
- s.add_development_dependency(%q<nokogiri>.freeze, ["~> 1.8"])
75
- else
76
- s.add_dependency(%q<activesupport>.freeze, ["> 4.1"])
77
- s.add_dependency(%q<test-unit>.freeze, ["~> 3.1"])
78
- s.add_dependency(%q<jeweler>.freeze, ["~> 2.0"])
79
- s.add_dependency(%q<nokogiri>.freeze, ["~> 1.8"])
80
- end
74
+ if s.respond_to? :add_runtime_dependency then
75
+ s.add_runtime_dependency(%q<activesupport>.freeze, ["> 4.1"])
76
+ s.add_development_dependency(%q<test-unit>.freeze, ["~> 3.1"])
77
+ s.add_development_dependency(%q<jeweler>.freeze, ["~> 2.0"])
78
+ s.add_development_dependency(%q<nokogiri>.freeze, ["~> 1.8"])
81
79
  else
82
80
  s.add_dependency(%q<activesupport>.freeze, ["> 4.1"])
83
81
  s.add_dependency(%q<test-unit>.freeze, ["~> 3.1"])
data/devlog.markdown CHANGED
@@ -1,3 +1,50 @@
1
+ #23.09.2019 23:08:08 CodingSession::END
2
+
3
+ some quick adjustments...
4
+
5
+ wkhtmltopdf does not work very well yet. it produces a huge canvas for some reason, making the actual table look miniature until zoomed in.
6
+ it's not a big issue, ii can open the generated html with safari and make an excellent pdf export.
7
+ but, why does it do it like that...
8
+
9
+ ahm, it seems to produce canvas sized as the current OS resolution, which then on this iMac becomes 5120x2880.
10
+
11
+ solved to a degree with: wkhtmltopdf --dpi 400 --viewport-size 600x800 --orientation Portrait
12
+
13
+ so now there's two more settings, a settings file might look like:
14
+
15
+ devlog_file: info/devlog.markdown
16
+ weekly_timesheet_template: info/weekly_timesheet.erb.html
17
+ convert_to_pdf_command: wkhtmltopdf --dpi 400 --viewport-size 600x800 --orientation Landscape
18
+
19
+ and that's it. will publish this as 0.3.3 if it turns out to work well.
20
+
21
+ #23.09.2019 19:39:39 CodingSession::BEGIN
22
+
23
+ #23.09.2019 01:04:21 CodingSession::END
24
+
25
+ took me some time to decide how to do this.
26
+
27
+ decided to generate a html from the pdf they gave.
28
+
29
+ that was easy, but turned out as rubbish, so ii did it manually.
30
+
31
+ then decided to populate that html with the data.
32
+
33
+ and then decided to use wkhtmltopdf command line utility to convert the html back to pdf.
34
+
35
+ have something, and it's configurable by devlogger. will need some more grind and polish.
36
+
37
+ #22.09.2019 19:05:17 CodingSession::BEGIN
38
+
39
+ #19.09.2019 23:34:08 CodingSession::END
40
+
41
+ adding something ii need for a dayjob. at end of period employer wants a timesheet filled out.
42
+ ii have no intent to do that manually ever again.
43
+
44
+ weekly daily report, ...
45
+
46
+ #19.09.2019 22:00:17 CodingSession::BEGIN
47
+
1
48
  #09.01.2018 23:38:01 CodingSession::END
2
49
 
3
50
  resolving a security issue reported by github. bumping nokogiri.
data/lib/devlog.rb CHANGED
@@ -226,7 +226,7 @@ module Devlog
226
226
  def save_info(devlog_file = 'devlog.markdown', info_file = 'info.markdown')
227
227
  info = parse_devlog_now(devlog_file)
228
228
  if info.has_info?
229
- File.open(File.join(File.dirname(devlog_file), info_file), 'w') {|f| f.write(info.to_info_string(short=true)) }
229
+ File.open(File.join(File.dirname(devlog_file), info_file), 'w') {|f| f.write(info.to_info_string(true)) }
230
230
  else
231
231
  puts "No info present.".red
232
232
  end
@@ -294,6 +294,131 @@ module Devlog
294
294
  devlog_export_file
295
295
  end
296
296
 
297
+ def weekly_pdf(tajm, weeks_from_now = 0, devlog_file = 'devlog.markdown')
298
+ require 'erb'
299
+ devlog_file = settings.devlog_file_setting || devlog_file
300
+ template = settings.has?(:weekly_timesheet_template) ? settings.weekly_timesheet_template : File.join(Devlog.path, 'templates', 'weekly_timesheet.erb.html')
301
+ convert_command = settings.has?(:convert_to_pdf_command) ? settings.convert_to_pdf_command : 'wkhtmltopdf'
302
+ puts "Using weekly template: #{template} #{settings.has?(:weekly_timesheet_template)}".green
303
+
304
+ zezzions = tajm.zezzions_for_week(weeks_from_now, DateTime.current)
305
+
306
+ if zezzions.any?
307
+ file_id = zezzions.last.zzbegin.strftime("%Y-%m-%d")
308
+ pdf = File.join(File.dirname(devlog_file), "sevendays-#{file_id}.pdf")
309
+ html = File.join(File.dirname(devlog_file), "sevendays-#{file_id}.html")
310
+ @sevendays = Sevendays.new(zezzions)
311
+
312
+ renderer = ERB.new(File.read(template))
313
+
314
+ File.open(html,'w') {|f| f.write(renderer.result()) }
315
+
316
+ `#{convert_command} #{html} #{pdf}`
317
+ else
318
+ 'No sessions to render.'.red
319
+ end
320
+ end
321
+
322
+ module SevendaysTotal
323
+ def total_hours
324
+ all.inject(0) { |time, zezzion| time + zezzion.session_time }.round(2)
325
+ end
326
+
327
+ def total_hours_string
328
+ total = total_hours
329
+
330
+ return "" if total <= 0
331
+
332
+ "#{total}h"
333
+ end
334
+ end
335
+
336
+ class Day
337
+ attr_accessor :all
338
+ include SevendaysTotal
339
+
340
+ def initialize(day, zezzions)
341
+ @all = zezzions.sort # sorting by default by zzbegin
342
+ @day = Sevendays::DAYS.include?(day) ? day : Sevendays::RANDOMDAY
343
+ end
344
+
345
+ def name
346
+ @day
347
+ end
348
+
349
+ def any?
350
+ all.any?
351
+ end
352
+
353
+ def begins_at
354
+ return '' unless any?
355
+ all.first.zzbegin.strftime('%H:%M')
356
+ end
357
+
358
+ def ends_at
359
+ return '' unless any?
360
+ all.last.zzend.strftime("%H:%M")
361
+ end
362
+
363
+ def breaks_at
364
+ return '' unless any?
365
+
366
+ size = all.size
367
+
368
+ return "" if size < 2
369
+
370
+ breaks = []
371
+ first = true
372
+ last = nil
373
+
374
+ all.each do |zezzion|
375
+ if first
376
+ last = zezzion
377
+ first = false
378
+ else
379
+ breaks << "#{last.zzend.strftime('%H:%M')} -> #{zezzion.zzbegin.strftime('%H:%M')}"
380
+ last = zezzion
381
+ end
382
+ end
383
+
384
+ breaks.join(', ')
385
+ end
386
+ end
387
+
388
+ class Sevendays
389
+ attr_accessor :all
390
+ include Devlog::SevendaysTotal
391
+
392
+ DAYS = %i(monday tuesday wednesday thursday friday saturday sunday).freeze
393
+ RANDOMDAY = 'Random'.freeze
394
+
395
+ def initialize(zezzions)
396
+ @all = zezzions.sort
397
+ end
398
+
399
+ def begins_at
400
+ all.first.zzbegin.strftime("%Y/%m/%d")
401
+ end
402
+
403
+ def ends_at
404
+ all.last.zzend.strftime("%Y/%m/%d")
405
+ end
406
+
407
+ def date
408
+ DateTime.current.strftime("%Y/%m/%d")
409
+ end
410
+
411
+ DAYS.each do |day|
412
+ attr_accessor day
413
+
414
+ define_method(day) do
415
+ value = Day.new(day, all.select { |zezzion| zezzion.zzbegin.send("#{day.to_s}?") } )
416
+ instance_variable_set("@__#{day.to_s}", value) unless instance_variable_get("@__#{day.to_s}")&.any?
417
+ instance_variable_get("@__#{day.to_s}")
418
+ end
419
+ end
420
+ end
421
+
297
422
  # The parsing object
298
423
  class Parsing
299
424
  # this is the total time, but each session has these same params
@@ -379,14 +504,37 @@ module Devlog
379
504
  (coding_session_time + com_session_time + payed_time).round(2)
380
505
  end
381
506
 
382
- # return hours worked for the last X days, from beginTime
383
- def hours_for_last(days, beginTime = DateTime.now)
384
- endTime = beginTime.to_time - days.days
385
- selected_zezzions = @zezzions.select { |z| z.zzbegin.to_time < beginTime && z.zzend >= endTime }
386
- # puts("Selected sessons from #{beginTime} to #{endTime}: #{selected_zezzions.size}")
507
+ # return hours worked for the last X days, from current_time
508
+ def hours_for_last(days, current_time = DateTime.now)
509
+ endTime = current_time.to_time - days.days
510
+ selected_zezzions = @zezzions.select { |z| z.zzbegin.to_time < current_time && z.zzend >= endTime }
511
+ #puts("Selected sessons from #{current_time} to #{endTime}: #{selected_zezzions.size}")
387
512
  selected_zezzions.inject(0) { |time, z| time + z.session_time }.round(2)
388
513
  end
389
514
 
515
+ # from time to time select some zezzions
516
+ def select_zezzions(from_time, to_time)
517
+ @zezzions.select { |z| z.zzbegin.to_time > from_time && z.zzend.to_time <= to_time }
518
+ end
519
+
520
+ # returns zezzions recorded during beginning of week and end of week
521
+ # fromnow - how many weeks into the past
522
+ def zezzions_for_week(fromnow = 0, current_time = DateTime.current)
523
+ moment = current_time - (7 * fromnow).days
524
+ begin_time = moment.beginning_of_week
525
+ end_time = moment.end_of_week
526
+
527
+ select_zezzions(begin_time, end_time)
528
+ end
529
+
530
+ def zezzions_for_month(fromnow = 0, current_time = DateTime.current_time)
531
+ moment = current_time - (fromnow).months
532
+ begin_time = moment.beginning_of_month
533
+ end_time = moment.end_of_month
534
+
535
+ select_zezzions(begin_time, end_time)
536
+ end
537
+
390
538
  def longest_session
391
539
  @zezzions.max_by(&:session_time)
392
540
  end
@@ -419,6 +567,10 @@ module Devlog
419
567
  @zezzions.last # devlog_end
420
568
  end
421
569
 
570
+ def last_payed_session
571
+ @zezzions.select{|zezzion| zezzion.payed_time<0}.first
572
+ end
573
+
422
574
  # return all sessions
423
575
  def devlog_sessions
424
576
  @zezzions
@@ -463,6 +615,36 @@ module Devlog
463
615
  s << ("Longest Session = #{self.longest_session.to_s}\n")
464
616
  s << ("Shortest Session = #{self.shortest_session.to_s}\n")
465
617
  s << ("Last Session = #{self.devlog_end.ago_in_words}, duration: #{self.last_session.session_time.round(3)} [h]")
618
+ s << ("\n")
619
+ s << ("Weekly Sessions\n")
620
+ s << ("\n")
621
+ sevendays = Sevendays.new(zezzions_for_week)
622
+ sevendays_total = 0
623
+ Sevendays::DAYS.each do |day|
624
+ current_day = sevendays.send(day.to_sym)
625
+ dayname = day.upcase
626
+ if current_day.any?
627
+ current_day_total_hours = current_day.total_hours
628
+ sevendays_total += current_day_total_hours
629
+ s << ("#{dayname.upcase}\n")
630
+ s << ("begins at: #{current_day.begins_at}\n")
631
+ s << ("breaks: #{current_day.breaks_at}\n")
632
+ s << ("end_at: #{current_day.ends_at}\n")
633
+ s << ("sum: #{current_day_total_hours}h\n")
634
+ s << ("\n")
635
+ end
636
+ end
637
+
638
+ 0.upto(5) do |week|
639
+ weekly_zezzions = zezzions_for_week(week, DateTime.current)
640
+ if weekly_zezzions.any?
641
+ sevendays = Sevendays.new(weekly_zezzions)
642
+ s << ("#{sevendays.begins_at}->#{sevendays.ends_at}: #{sevendays.total_hours_string}\n")
643
+ else
644
+ s << "No weekly sessions for week #{week}.\n"
645
+ end
646
+ end
647
+ s << "Last payed: #{last_payed_session.zzend.to_s(:long)}" if last_payed_session
466
648
  end
467
649
  s
468
650
  end
@@ -486,6 +668,8 @@ module Devlog
486
668
  end
487
669
 
488
670
  class Zezzion
671
+ include Comparable
672
+
489
673
  COM = 1 # communication session
490
674
  COD = 0 # coding session
491
675
  attr_accessor :zzbegin, :zzend, :zzbegin_title, :zzend_title, :zztype
@@ -506,6 +690,10 @@ module Devlog
506
690
  @zzend_line_number = 0
507
691
  end
508
692
 
693
+ def <=>(other)
694
+ zzbegin <=> other.zzbegin
695
+ end
696
+
509
697
  # in seconds
510
698
  def time
511
699
  @zzend.to_time - @zzbegin.to_time
@@ -516,6 +704,7 @@ module Devlog
516
704
  min = self.time / 60
517
705
  hours = min / 60
518
706
  days = hours / 24
707
+ days
519
708
  end
520
709
 
521
710
  # the whole coding session time
@@ -8,6 +8,10 @@ module Devlog
8
8
  # Allow settings.key besides settings[:key]
9
9
  # If the method name exists as a key within this Hash, fetch it.
10
10
  class Settings < Hash
11
+ def has?(m)
12
+ return key?(m) || key?(m.to_s)
13
+ end
14
+
11
15
  def method_missing(m, *args, &block)
12
16
  if key?(m)
13
17
  fetch m
@@ -29,7 +33,7 @@ module Devlog
29
33
  end
30
34
 
31
35
  def settings
32
- @settings
36
+ @settings ||= Settings.new
33
37
  end
34
38
 
35
39
  # The default is the current folder with devlog.markdown in it.
@@ -37,12 +41,22 @@ module Devlog
37
41
 
38
42
  # Calculate a devlog_file path.
39
43
  def devlog_file_setting
40
- return DEVLOG_FILE unless @settings
41
- devlog_file_setting = @settings['devlog_file']
42
- if devlog_file_setting && File.exists?(File.join(Dir.pwd, devlog_file_setting))
44
+ return DEVLOG_FILE unless settings
45
+ devlog_file_setting = settings['devlog_file']
46
+ if devlog_file_setting && File.exist?(File.join(Dir.pwd, devlog_file_setting))
43
47
  devlog_file_setting
44
48
  else
45
49
  DEVLOG_FILE
46
50
  end
47
51
  end
52
+
53
+ def devlog_timezone_setting
54
+ return 'Amsterdam' unless settings
55
+ devlog_timezone_setting = settings['timezone']
56
+ if devlog_timezone_setting.present?
57
+ devlog_timezone_setting
58
+ else
59
+ 'Amsterdam'
60
+ end
61
+ end
48
62
  end
Binary file
@@ -0,0 +1,71 @@
1
+ <!doctype html>
2
+ <html>
3
+ <head><meta http-equiv=Content-Type content="text/html; charset=UTF-8">
4
+ <style type="text/css">
5
+ <!--
6
+ span.cls_005{font-family:Arial,serif;font-size:10.1px;color:rgb(118,112,113);font-weight:normal;font-style:normal;text-decoration: none}
7
+ div.cls_005{font-family:Arial,serif;font-size:10.1px;color:rgb(118,112,113);font-weight:normal;font-style:normal;text-decoration: none}
8
+ span.cls_003{font-family:Arial,serif;font-size:11.1px;color:rgb(118,112,113);font-weight:bold;font-style:normal;text-decoration: none}
9
+ div.cls_003{font-family:Arial,serif;font-size:11.1px;color:rgb(118,112,113);font-weight:bold;font-style:normal;text-decoration: none}
10
+ span.cls_006{font-family:Arial,serif;font-size:11.1px;color:rgb(118,112,113);font-weight:normal;font-style:normal;text-decoration: none}
11
+ div.cls_006{font-family:Arial,serif;font-size:11.1px;color:rgb(118,112,113);font-weight:normal;font-style:normal;text-decoration: none}
12
+ -->
13
+
14
+ .time {
15
+ font-family:Arial,serif;font-size:8px;color:rgb(118,112,113);font-weight:bold;font-style:normal;text-decoration: none
16
+ }
17
+ </style>
18
+ </head>
19
+ <body style="width:900px;">
20
+ <div style="position:absolute;left:50%;margin-left:-420px;top:0px;width:841px;height:595px;overflow:hidden">
21
+ <div style="position:absolute;left:0px;top:0px">
22
+ <img src="background.jpg" width=841 height=589></div>
23
+ <div style="position:absolute;left:441.59px;top:158.60px" class="cls_005"><span class="cls_005">Clients Name</span></div>
24
+ <div style="position:absolute;left:441.59px;top:173.71px" class="cls_005"><span class="cls_005">Contract Number</span></div>
25
+ <div style="position:absolute;left:441.59px;top:189.07px" class="cls_005"><span class="cls_005">Consultancy Company Name</span></div>
26
+ <div style="position:absolute;left:53.51px;top:191.72px" class="cls_003"><span class="cls_003">WEEK COMMENCING</span></div>
27
+ <div style="position:absolute;left:225px;top:193.72px" class="cls_006"><span class="time week-comencing"><%= @sevendays.begins_at %></span></div>
28
+
29
+
30
+ <div style="position:absolute;left:441.59px;top:204.19px" class="cls_005"><span class="cls_005">Consultants Name</span></div>
31
+
32
+
33
+ <!-- The weekly timesheet table -->
34
+ <div style="position:absolute;left:54.71px;top:234.44px" class="cls_003"><span class="cls_003">DAY</span></div>
35
+ <div style="position:absolute;left:146.39px;top:234.44px" class="cls_003"><span class="cls_003">START TIME</span></div>
36
+ <div style="position:absolute;left:252.71px;top:234.44px" class="cls_003"><span class="cls_003">BREAK/S START & FINISH</span></div>
37
+ <div style="position:absolute;left:578.87px;top:234.44px" class="cls_003"><span class="cls_003">END TIME</span></div>
38
+ <div style="position:absolute;left:685.19px;top:234.44px" class="cls_003"><span class="cls_003">TOTAL HOURS</span></div>
39
+
40
+ <% top = 251 %>
41
+ <% %w[monday tuesday wednesday thursday friday saturday sunday].each do |day| %>
42
+ <% current_day = @sevendays.send(day.to_sym) %>
43
+ <% dayname = day.upcase %>
44
+ <div style="position:absolute;left:54.71px;top:<%= top.to_s %>px" class="cls_006"><span class="cls_006"><%= dayname %></span></div>
45
+ <div style="position:absolute;left:146.39px;top:<%= top.to_s %>px" class="cls_006"><span class="time <%= day %> start-time"><%= current_day.begins_at %></span></div>
46
+ <div style="position:absolute;left:252.7px;top:<%= top.to_s %>px" class="cls_006"><span class="time <%= day %> breaks"><%= current_day.breaks_at %></span></div>
47
+ <div style="position:absolute;left:578.8px;top:<%= top.to_s %>px" class="cls_006"><span class="time <%= day %> end-time"><%= current_day.ends_at %></span></div>
48
+ <div style="position:absolute;left:685.19px;top:<%= top.to_s %>px" class="cls_006"><span class="time <%= day %> total-hours"><%= current_day.total_hours %></span></div>
49
+ <% top += 16 %>
50
+ <%end%>
51
+
52
+ <div style="position:absolute;left:55.43px;top:380.83px" class="cls_006"><span class="cls_006">Notes Regarding Overtime or Expenses:</span></div>
53
+ <div style="position:absolute;left:60.43px;top:410.83px" class="cls_006"><span class="cls_006"><%= @sevendays.total_hours_string %></span></div>
54
+
55
+ <div style="position:absolute;left:54.71px;top:450.43px" class="cls_006"><span class="cls_006">Signed by Consultant</span></div>
56
+ <div style="position:absolute;left:200.71px;top:450.43px" class="cls_006"><span class="cls_006"></span></div>
57
+
58
+ <div style="position:absolute;left:467.03px;top:451.88px" class="cls_006"><span class="cls_006">Signed by Client</span></div>
59
+ <div style="position:absolute;left:54.71px;top:468.67px" class="cls_006"><span class="cls_006">Print Name</span></div>
60
+ <div style="position:absolute;left:200.71px;top:468.67px" class="cls_006"><span class="cls_006"></span></div>
61
+
62
+ <div style="position:absolute;left:467.03px;top:471.32px" class="cls_006"><span class="cls_006">Job Title</span></div>
63
+ <div style="position:absolute;left:54.71px;top:488.83px" class="cls_006"><span class="cls_006">Date</span></div>
64
+ <div style="position:absolute;left:200px;top:488.83px" class="cls_006"><span class="date"><%= @sevendays.date %></span></div>
65
+ <div style="position:absolute;left:467.03px;top:491.71px" class="cls_006"><span class="cls_006">Print Name</span></div>
66
+ <div style="position:absolute;left:467.03px;top:511.16px" class="cls_006"><span class="cls_006">Date</span></div>
67
+ </div>
68
+ </body>
69
+ </html>
70
+
71
+
@@ -26,6 +26,8 @@ class DevlogSettingsTest < Test::Unit::TestCase
26
26
  def test_loading_from_yaml
27
27
  assert(settings.devlog_file == 'development_log.markdown',
28
28
  'example setting should be loaded')
29
+ assert(settings.timezone == 'Amsterdam',
30
+ 'example setting should be loaded')
29
31
  end
30
32
 
31
33
  def test_devlog_file_setting_returns_default_when_overriden_devlog_file_does_not_exist
data/test/devlog_test.rb CHANGED
@@ -189,7 +189,7 @@ class DevlogTest < Test::Unit::TestCase
189
189
 
190
190
  def test_devlog_export
191
191
  @exported_devlog = export_devlog_now(File.join(File.dirname(__FILE__), TEST_FILES_PATH, 'test_devlog_export.markdown'))
192
- assert(File.exists?(@exported_devlog))
192
+ assert(File.exist?(@exported_devlog))
193
193
  assert(File.size(@exported_devlog)>0, "file should not be empty")
194
194
  File.open(@exported_devlog, "r") do |f|
195
195
  first = f.readline
@@ -207,4 +207,48 @@ class DevlogTest < Test::Unit::TestCase
207
207
  def test_default_devlog_file_setting
208
208
  assert(devlog_file_setting == 'devlog.markdown', 'should return default')
209
209
  end
210
+
211
+ def test_zezzions_for_week
212
+ load_devlog_weekly
213
+ assert(@tajm_weekly.devlog_sessions.size==15, "should be 15, but is #{@tajm_weekly.devlog_sessions.size}")
214
+
215
+ zezzions = @tajm_weekly.zezzions_for_week(0, DateTime.new(2019, 9, 11, 18, 0, 0))
216
+
217
+ assert(zezzions.size == 4, 'should be 4 but is not')
218
+
219
+ zezzions = @tajm_weekly.zezzions_for_week(1, DateTime.new(2019, 9, 11, 18, 0, 0))
220
+
221
+ assert(zezzions.size == 10, "should be 10 but is #{zezzions.size}")
222
+
223
+ zezzions = @tajm_weekly.zezzions_for_week(2, DateTime.new(2019, 9, 11, 18, 0, 0))
224
+
225
+ assert(zezzions.size == 1, "should be 1 but is #{zezzions.size}")
226
+
227
+ zezzions = @tajm_weekly.zezzions_for_week(0, DateTime.new(2019, 9, 6, 23, 0, 0))
228
+
229
+ assert(zezzions.size == 10, "should be 10 but is #{zezzions.size}")
230
+ end
231
+
232
+ def test_weekly_timesheet_html_generation
233
+ load_devlog_weekly
234
+
235
+ @sevendays = Sevendays.new(@tajm_weekly.zezzions_for_week(0, DateTime.new(2019, 9, 6, 23, 0, 0)))
236
+
237
+ assert(@sevendays.monday.begins_at == "08:00", "monday should begin at 08:00 but begins at #{@sevendays.monday.begins_at}")
238
+ assert(@sevendays.monday.ends_at == "16:00", "monday should end at 16:00 but ends at #{@sevendays.monday.ends_at}")
239
+
240
+ assert(@sevendays.tuesday.begins_at == "08:00", "tuesday should begin at 08:00 but begins at #{@sevendays.tuesday.begins_at}")
241
+ assert(@sevendays.tuesday.ends_at == "22:00", "tuesday should end at 22:00 but ends at #{@sevendays.tuesday.ends_at}")
242
+
243
+ assert(@sevendays.friday.begins_at == "08:00", "friday should begin at 08:00 but begins at #{@sevendays.friday.begins_at}")
244
+ assert(@sevendays.friday.ends_at == "18:00", "friday should end at 18:00 but ends at #{@sevendays.friday.ends_at}")
245
+
246
+ assert(@sevendays.begins_at == "2019/09/02", "seven days should begin on 2019/09/02 but beings on #{@sevendays.begins_at}")
247
+
248
+ assert(@sevendays.sunday.breaks_at == "", "no breaks on sunday but is: #{@sevendays.sunday.breaks_at}")
249
+
250
+ assert(@sevendays.friday.breaks_at == "12:00 -> 14:00", "one break on friday but is: #{@sevendays.friday.breaks_at}")
251
+
252
+ assert(@sevendays.tuesday.breaks_at == "12:00 -> 13:00, 15:00 -> 20:00", "two breaks on tuesday but is: #{@sevendays.tuesday.breaks_at}")
253
+ end
210
254
  end
@@ -1 +1,2 @@
1
- devlog_file: "test/test_devlogs/test_devlog.markdown"
1
+ devlog_file: "test/test_devlogs/test_devlog.markdown"
2
+ timezone: 'Ljubljana'
@@ -1,5 +1,5 @@
1
1
  # Override the default location of the_project_folder_path/../info/devlog.markdown
2
2
  devlog_file: development_log.markdown
3
-
3
+ timezone: Amsterdam
4
4
  nested:
5
5
  setting: xyz
@@ -0,0 +1,89 @@
1
+ #11.09.2019 17:00:00 CodingSession::END
2
+
3
+ Wednesday
4
+
5
+ #11.09.2019 13:00:00 CodingSession::BEGIN
6
+
7
+ #11.09.2019 12:00:00 CodingSession::END
8
+
9
+ Wednesday
10
+
11
+ #11.09.2019 08:00:00 CodingSession::BEGIN
12
+
13
+ #10.09.2019 16:00:00 CodingSession::END
14
+
15
+ Tuesday
16
+
17
+ #10.09.2019 08:00:00 CodingSession::BEGIN
18
+
19
+ #09.09.2019 16:00:00 CodingSession::END
20
+
21
+ Monday
22
+
23
+ #09.09.2019 08:00:00 CodingSession::BEGIN
24
+
25
+ #08.09.2019 16:00:00 CodingSession::END
26
+
27
+ Sunday
28
+
29
+ #08.09.2019 08:00:00 CodingSession::BEGIN
30
+
31
+ #07.09.2019 16:00:00 CodingSession::END
32
+
33
+ Saturday
34
+
35
+ #07.09.2019 08:00:00 CodingSession::BEGIN
36
+
37
+ #06.09.2019 18:00:00 CodingSession::END
38
+
39
+ Friday
40
+
41
+ #06.09.2019 14:00:00 CodingSession::BEGIN
42
+
43
+ #06.09.2019 12:00:00 CodingSession::END
44
+
45
+ Friday
46
+
47
+ #06.09.2019 08:00:00 CodingSession::BEGIN
48
+
49
+ #05.09.2019 16:00:00 CodingSession::END
50
+
51
+ Thursday
52
+
53
+ #05.09.2019 08:00:00 CodingSession::BEGIN
54
+
55
+ #04.09.2019 16:00:00 CodingSession::END
56
+
57
+ Wednesday
58
+
59
+ #04.09.2019 08:00:00 CodingSession::BEGIN
60
+
61
+ #03.09.2019 22:00:00 CodingSession::END
62
+
63
+ Tuesday 3
64
+
65
+ #03.09.2019 20:00:00 CodingSession::BEGIN
66
+
67
+ #03.09.2019 15:00:00 CodingSession::END
68
+
69
+ Tuesday 2
70
+
71
+ #03.09.2019 13:00:00 CodingSession::BEGIN
72
+
73
+ #03.09.2019 12:00:00 CodingSession::END
74
+
75
+ Tuesday 1
76
+
77
+ #03.09.2019 08:00:00 CodingSession::BEGIN
78
+
79
+ #02.09.2019 16:00:00 CodingSession::END
80
+
81
+ Monday
82
+
83
+ #02.09.2019 08:00:00 CodingSession::BEGIN
84
+
85
+ #01.09.2019 16:00:00 CodingSession::END
86
+
87
+ Sunday
88
+
89
+ #01.09.2019 08:00:00 CodingSession::BEGIN
data/test/test_helper.rb CHANGED
@@ -12,6 +12,10 @@ end
12
12
  TEST_FILES_PATH = 'test_devlogs'.freeze
13
13
  TEMP_PATH = '../tmp'.freeze
14
14
 
15
+ def parse_test_devlog(filename)
16
+ parse_devlog_now(File.join(File.dirname(__FILE__), TEST_FILES_PATH, filename))
17
+ end
18
+
15
19
  def load_devlog
16
20
  @tajm = parse_devlog_now(File.join(File.dirname(__FILE__), '..', 'devlog.markdown'))
17
21
  puts "#{@tajm.coding_session_time} #{@tajm.com_session_time} #{@tajm.payed_time}"
@@ -29,7 +33,7 @@ def load_devlog_now
29
33
  end
30
34
 
31
35
  def load_devlog_test
32
- @tajm_test = parse_devlog_now(File.join(File.dirname(__FILE__), TEST_FILES_PATH, 'test_devlog.markdown'))
36
+ @tajm_test = parse_test_devlog('test_devlog.markdown')
33
37
  puts "#{@tajm_test.coding_session_time} #{@tajm_test.com_session_time} #{@tajm_test.payed_time}"
34
38
  assert(@tajm_test.coding_session_time>0, "truth")
35
39
  assert(@tajm_test.com_session_time>0, "love")
@@ -37,13 +41,17 @@ def load_devlog_test
37
41
  end
38
42
 
39
43
  def load_devlog_stat
40
- @tajm_stat = parse_devlog_now(File.join(File.dirname(__FILE__), TEST_FILES_PATH, 'test_stats_devlog.markdown'))
44
+ @tajm_stat = parse_test_devlog('test_stats_devlog.markdown')
41
45
  end
42
46
 
43
47
  def load_devlog_single
44
- @tajm_single = parse_devlog_now(File.join(File.dirname(__FILE__), TEST_FILES_PATH, 'test_single_devlog.markdown'))
48
+ @tajm_single = parse_test_devlog('test_single_devlog.markdown')
45
49
  end
46
50
 
47
51
  def load_devlog_negative
48
- @tajm_negative = parse_devlog_now(File.join(File.dirname(__FILE__), TEST_FILES_PATH, 'test_negative_devlog.markdown'))
52
+ @tajm_negative = parse_test_devlog('test_negative_devlog.markdown')
53
+ end
54
+
55
+ def load_devlog_weekly
56
+ @tajm_weekly = parse_test_devlog('test_weekly_devlog.markdown')
49
57
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: devlog
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.3.2
4
+ version: 0.3.5
5
5
  platform: ruby
6
6
  authors:
7
7
  - mihael
8
- autorequire:
8
+ autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2018-06-01 00:00:00.000000000 Z
11
+ date: 2023-09-25 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: activesupport
@@ -75,9 +75,9 @@ extra_rdoc_files:
75
75
  - LICENSE
76
76
  - README.md
77
77
  files:
78
+ - ".github/workflows/devlog_test.yml"
78
79
  - ".ruby-gemset"
79
80
  - ".ruby-version"
80
- - ".travis.yml"
81
81
  - Gemfile
82
82
  - LICENSE
83
83
  - README.md
@@ -98,6 +98,8 @@ files:
98
98
  - sublime_text/devlog.tmbundle/Snippets/tu.tmSnippet
99
99
  - sublime_text/devlog.tmbundle/info.plist
100
100
  - sublime_text/tu.py
101
+ - templates/background.jpg
102
+ - templates/weekly_timesheet.erb.html
101
103
  - test/devlog_file_test.rb
102
104
  - test/devlog_settings_test.rb
103
105
  - test/devlog_test.rb
@@ -111,13 +113,14 @@ files:
111
113
  - test/test_devlogs/test_settings.yml
112
114
  - test/test_devlogs/test_single_devlog.markdown
113
115
  - test/test_devlogs/test_stats_devlog.markdown
116
+ - test/test_devlogs/test_weekly_devlog.markdown
114
117
  - test/test_helper.rb
115
118
  - tmp/.gitignore
116
119
  homepage: http://github.com/mihael/devlog
117
120
  licenses:
118
121
  - MIT
119
122
  metadata: {}
120
- post_install_message:
123
+ post_install_message:
121
124
  rdoc_options: []
122
125
  require_paths:
123
126
  - lib
@@ -132,9 +135,8 @@ required_rubygems_version: !ruby/object:Gem::Requirement
132
135
  - !ruby/object:Gem::Version
133
136
  version: '0'
134
137
  requirements: []
135
- rubyforge_project:
136
- rubygems_version: 2.5.2
137
- signing_key:
138
+ rubygems_version: 3.2.15
139
+ signing_key:
138
140
  specification_version: 4
139
141
  summary: takes devlog.markdown and gives info
140
142
  test_files: []
data/.travis.yml DELETED
@@ -1,8 +0,0 @@
1
- language: ruby
2
- rvm:
3
- #- "1.9.3"
4
- - "2.3.0"
5
- #before_install:
6
- # - bundle update rdoc
7
- # uncomment this line if your project needs to run something other than `rake`:
8
- # script: bundle exec rspec spec