doing 1.0.64 → 1.0.65
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/README.md +24 -1
- data/bin/doing +8 -5
- data/lib/doing/version.rb +1 -1
- data/lib/doing/wwid.rb +46 -5
- metadata +2 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: a774718572df78395293b6294bcfa4bac94cfe2cde0ffec43e8bbea60b874534
|
4
|
+
data.tar.gz: fba4b65439084eae5b291bd65f5a1d14d49e5b5c4c8b70abd5e8f73fa39b3545
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 01bf52dbc6e7077e6ff2a67ab22504dda4be927f31da8be7e5383136b5cac500cd7920203b7383ebe302af5ddce375e0ee7389273a275edfde27971de8ae87bb
|
7
|
+
data.tar.gz: 79e7b8dcf00223118a0e3f5bb648ed33e920dc915909f62d1c21f2a19332f3d35336d3e5ca85a31632416b9fb9364d58db2fb6a4f90e7a200bc7cb706f76e14b
|
data/README.md
CHANGED
@@ -29,7 +29,7 @@ _Side note:_ I actually use the library behind this utility as part of another s
|
|
29
29
|
|
30
30
|
## Installation
|
31
31
|
|
32
|
-
The current version of `doing` is <!--VER-->1.0.
|
32
|
+
The current version of `doing` is <!--VER-->1.0.64<!--END VER-->.
|
33
33
|
|
34
34
|
$ [sudo] gem install doing
|
35
35
|
|
@@ -595,6 +595,29 @@ Example: Archive all Currently items for _@client_ that are marked _@done_
|
|
595
595
|
|
596
596
|
doing archive @client @done
|
597
597
|
|
598
|
+
##### Importing
|
599
|
+
|
600
|
+
Doing can currently only import tasks from Timing.app reports. If you want to sync up your Doing file with Timing's tracking:
|
601
|
+
|
602
|
+
1. Open Timing and go to Reports
|
603
|
+
2. Set the date span you want to import into doing
|
604
|
+
3. Group by Project, Then by None
|
605
|
+
4. Include Tasks with Title, (not as subgroup), Timespan, and Notes
|
606
|
+
5. Uncheck App Usage
|
607
|
+
6. Set File Format to JSON and Duration format to "XX:YY:ZZ"
|
608
|
+
7. Include short entries if desired
|
609
|
+
8. Export the report to a new file
|
610
|
+
|
611
|
+
Now you can run `doing import --type timing -s SECTION PATH`, where SECTION is the name of the section you want to import the entries to (defauts to Currently), and PATH is the path to the JSON file. You can also add a tag (or tags) to all entries, or a custom prefix.
|
612
|
+
|
613
|
+
(`--type timing` is the only option right now, so it doesn't need to be included)
|
614
|
+
|
615
|
+
# Import entries to Projects section and add @timing to all new entries
|
616
|
+
doing import -s Projects --tag=timing "~/Desktop/All Activities.json"
|
617
|
+
|
618
|
+
# Import to default section (Currently) and prefix entries with '[Imported]'
|
619
|
+
doing import --prefix="[Imported]" "~/Desktop/All Activities.json"
|
620
|
+
|
598
621
|
---
|
599
622
|
|
600
623
|
## Extras
|
data/bin/doing
CHANGED
@@ -1394,10 +1394,10 @@ end
|
|
1394
1394
|
desc 'Import entries from an external source'
|
1395
1395
|
long_desc 'Imports entries from other sources. Currently only handles JSON reports exported from Timing.app.'
|
1396
1396
|
arg_name 'PATH'
|
1397
|
-
command
|
1397
|
+
command :import do |c|
|
1398
1398
|
c.desc 'Import type'
|
1399
1399
|
c.arg_name 'TYPE'
|
1400
|
-
c.flag
|
1400
|
+
c.flag :type, default_value: 'timing'
|
1401
1401
|
|
1402
1402
|
c.desc 'Target section'
|
1403
1403
|
c.arg_name 'NAME'
|
@@ -1405,11 +1405,14 @@ command [:import] do |c|
|
|
1405
1405
|
|
1406
1406
|
c.desc 'Tag all imported entries'
|
1407
1407
|
c.arg_name 'TAGS'
|
1408
|
-
c.flag
|
1408
|
+
c.flag :tag
|
1409
1409
|
|
1410
1410
|
c.desc 'Prefix entries with'
|
1411
1411
|
c.arg_name 'PREFIX'
|
1412
|
-
c.flag
|
1412
|
+
c.flag :prefix
|
1413
|
+
|
1414
|
+
c.desc 'Allow entries that overlap existing times'
|
1415
|
+
c.switch [:overlap], negatable: true
|
1413
1416
|
|
1414
1417
|
c.action do |_global_options, options, args|
|
1415
1418
|
|
@@ -1417,7 +1420,7 @@ command [:import] do |c|
|
|
1417
1420
|
|
1418
1421
|
if options[:type] =~ /^tim/i
|
1419
1422
|
args.each do |path|
|
1420
|
-
wwid.import_timing(path, { section: section, tag: options[:tag], prefix: options[:prefix] })
|
1423
|
+
wwid.import_timing(path, { section: section, tag: options[:tag], prefix: options[:prefix], no_overlap: !options[:overlap] })
|
1421
1424
|
wwid.write(wwid.doing_file)
|
1422
1425
|
end
|
1423
1426
|
else
|
data/lib/doing/version.rb
CHANGED
data/lib/doing/wwid.rb
CHANGED
@@ -7,7 +7,7 @@ require 'pp'
|
|
7
7
|
##
|
8
8
|
## @brief Hash helpers
|
9
9
|
##
|
10
|
-
class Hash
|
10
|
+
class ::Hash
|
11
11
|
def has_tags?(tags, bool = 'AND')
|
12
12
|
tags = tags.split(/ *, */) if tags.is_a? String
|
13
13
|
item = self
|
@@ -667,6 +667,40 @@ class WWID
|
|
667
667
|
@results.push(%(Added "#{entry['title']}" to #{section}))
|
668
668
|
end
|
669
669
|
|
670
|
+
def same_time?(item_a, item_b)
|
671
|
+
item_a['date'] == item_b['date'] ? get_interval(item_a, false) == get_interval(item_b, false) : false
|
672
|
+
end
|
673
|
+
|
674
|
+
def overlapping_time?(item_a, item_b)
|
675
|
+
return true if same_time?(item_a, item_b)
|
676
|
+
|
677
|
+
start_a = item_a['date']
|
678
|
+
interval = get_interval(item_a, false)
|
679
|
+
end_a = interval ? start_a + interval.to_i : start_a
|
680
|
+
start_b = item_b['date']
|
681
|
+
interval = get_interval(item_b, false)
|
682
|
+
end_b = interval ? start_b + interval.to_i : start_b
|
683
|
+
(start_a >= start_b && start_a <= end_b) || (end_a >= start_b && end_a <= end_b) || (start_a < start_b && end_a > end_b)
|
684
|
+
end
|
685
|
+
|
686
|
+
def dedup(items, no_overlap = false)
|
687
|
+
|
688
|
+
combined = []
|
689
|
+
@content.each do |_k, v|
|
690
|
+
combined += v['items']
|
691
|
+
end
|
692
|
+
|
693
|
+
items.delete_if do |item|
|
694
|
+
duped = false
|
695
|
+
combined.each do |comp|
|
696
|
+
duped = no_overlap ? overlapping_time?(item, comp) : same_time?(item, comp)
|
697
|
+
break if duped
|
698
|
+
end
|
699
|
+
# warn "Skipping overlapping entry: #{item['title']}" if duped
|
700
|
+
duped
|
701
|
+
end
|
702
|
+
end
|
703
|
+
|
670
704
|
##
|
671
705
|
## @brief Imports a Timing report
|
672
706
|
##
|
@@ -676,6 +710,8 @@ class WWID
|
|
676
710
|
##
|
677
711
|
def import_timing(path, opt = {})
|
678
712
|
section = opt[:section] || @current_section
|
713
|
+
opt[:no_overlap] ||= false
|
714
|
+
|
679
715
|
add_section(section) unless @content.has_key?(section)
|
680
716
|
|
681
717
|
add_tags = opt[:tag] ? opt[:tag].split(/[ ,]+/).map { |t| t.sub(/^@?/, '@') }.join(' ') : ''
|
@@ -690,10 +726,12 @@ class WWID
|
|
690
726
|
# Only process entries with a start and end date
|
691
727
|
next unless entry.key?('startDate') && entry.key?('endDate')
|
692
728
|
|
693
|
-
|
694
|
-
|
729
|
+
# Round down seconds and convert UTC to local time
|
730
|
+
start_time = Time.parse(entry['startDate'].sub(/:\d\dZ$/, ':00Z')).getlocal
|
731
|
+
end_time = Time.parse(entry['endDate'].sub(/:\d\dZ$/, ':00Z')).getlocal
|
695
732
|
next unless start_time && end_time
|
696
|
-
|
733
|
+
|
734
|
+
tags = entry['project'].split(/ ▸ /).map {|proj| proj.gsub(/[^a-z0-9]+/i, '').downcase }
|
697
735
|
title = "#{prefix} "
|
698
736
|
title += entry.key?('activityTitle') && entry['activityTitle'] != '(Untitled Task)' ? entry['activityTitle'] : 'Working on'
|
699
737
|
tags.each do |tag|
|
@@ -711,7 +749,10 @@ class WWID
|
|
711
749
|
new_entry['note'] = entry['notes'].split(/\n/).map(&:chomp) if entry.key?('notes')
|
712
750
|
new_items.push(new_entry)
|
713
751
|
end
|
714
|
-
|
752
|
+
total = new_items.count
|
753
|
+
new_items = dedup(new_items, opt[:no_overlap])
|
754
|
+
dups = total - new_items.count
|
755
|
+
@results.push(%(Skipped #{dups} items with overlapping times)) if dups > 0
|
715
756
|
@content[section]['items'].concat(new_items)
|
716
757
|
@results.push(%(Imported #{new_items.count} items to #{section}))
|
717
758
|
end
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: doing
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 1.0.
|
4
|
+
version: 1.0.65
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Brett Terpstra
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2021-07-
|
11
|
+
date: 2021-07-24 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: rake
|